1pub mod data_stack;
2pub mod lifetime;
3pub mod managed;
4pub mod managed_box;
5pub mod shared;
6pub mod type_hash;
7
8pub mod prelude {
9 pub use crate::{
10 Finalize, Initialize, data_stack::*, lifetime::*, managed::*, managed_box::*, shared::*,
11 type_hash::*,
12 };
13}
14
15pub trait Initialize: Sized {
16 fn initialize() -> Self;
17
18 unsafe fn initialize_raw(data: *mut ()) {
20 unsafe { data.cast::<Self>().write(Self::initialize()) };
21 }
22}
23
24impl<T> Initialize for T
25where
26 T: Default,
27{
28 fn initialize() -> Self {
29 Self::default()
30 }
31}
32
33pub trait Finalize: Sized {
34 unsafe fn finalize_raw(data: *mut ()) {
36 unsafe { data.cast::<Self>().read_unaligned() };
37 }
38}
39
40impl<T> Finalize for T {}
41
42#[inline]
43pub fn pointer_alignment_padding(pointer: *const u8, alignment: usize) -> usize {
44 let mut result = (pointer as usize) % alignment;
45 if result > 0 {
46 result = alignment - result;
47 }
48 result
49}
50
51pub unsafe fn non_zero_alloc(mut layout: std::alloc::Layout) -> *mut u8 {
53 unsafe {
54 if layout.size() == 0 {
55 layout = std::alloc::Layout::from_size_align_unchecked(1, layout.align());
56 }
57 let result = std::alloc::alloc(layout);
58 #[cfg(feature = "alloc-backtrace")]
59 println!(
60 "* Alloc {:p} ({:?}):\n{}",
61 result,
62 layout,
63 std::backtrace::Backtrace::force_capture()
64 );
65 result
66 }
67}
68
69pub unsafe fn non_zero_dealloc(ptr: *mut u8, mut layout: std::alloc::Layout) {
71 unsafe {
72 if layout.size() == 0 {
73 layout = std::alloc::Layout::from_size_align_unchecked(1, layout.align());
74 }
75 #[cfg(feature = "alloc-backtrace")]
76 println!(
77 "* Dealloc {:p} ({:?}):\n{}",
78 ptr,
79 layout,
80 std::backtrace::Backtrace::force_capture()
81 );
82 std::alloc::dealloc(ptr, layout);
83 }
84}
85
86pub unsafe fn non_zero_realloc(
88 ptr: *mut u8,
89 mut layout: std::alloc::Layout,
90 new_size: usize,
91) -> *mut u8 {
92 unsafe {
93 if layout.size() == 0 {
94 layout = std::alloc::Layout::from_size_align_unchecked(1, layout.align());
95 }
96 let result = std::alloc::realloc(ptr, layout, new_size);
97 #[cfg(feature = "alloc-backtrace")]
98 println!(
99 "* Realloc {:p} -> {:p} ({:?}):\n{}",
100 ptr,
101 result,
102 layout,
103 std::backtrace::Backtrace::force_capture()
104 );
105 result
106 }
107}
108
109pub unsafe fn non_zero_alloc_zeroed(mut layout: std::alloc::Layout) -> *mut u8 {
111 unsafe {
112 if layout.size() == 0 {
113 layout = std::alloc::Layout::from_size_align_unchecked(1, layout.align());
114 }
115 let result = std::alloc::alloc_zeroed(layout);
116 #[cfg(feature = "alloc-backtrace")]
117 println!(
118 "* Alloc zeroed {:p} ({:?}):\n{}",
119 result,
120 layout,
121 std::backtrace::Backtrace::force_capture()
122 );
123 result
124 }
125}
126
127#[macro_export]
128macro_rules! does_implement_trait {
129 ($trait:path => $identifier:ident < $type:ident >) => {
130 pub fn $identifier<$type>() -> bool {
131 struct ImplementsTrait<'a, $type> {
132 implements: &'a std::cell::Cell<bool>,
133 _marker: std::marker::PhantomData<$type>,
134 }
135
136 #[allow(clippy::non_canonical_clone_impl)]
137 impl<$type> Clone for ImplementsTrait<'_, $type> {
138 fn clone(&self) -> Self {
139 self.implements.set(false);
140 ImplementsTrait {
141 implements: self.implements,
142 _marker: std::marker::PhantomData,
143 }
144 }
145 }
146
147 impl<$type: $trait> Copy for ImplementsTrait<'_, $type> {}
148
149 let implements = std::cell::Cell::new(true);
150 let _ = [ImplementsTrait::<$type> {
151 implements: &implements,
152 _marker: std::marker::PhantomData,
153 }]
154 .clone();
155 implements.get()
156 }
157 };
158}
159
160does_implement_trait!(Send => is_send<T>);
161does_implement_trait!(Sync => is_sync<T>);
162does_implement_trait!(Copy => is_copy<T>);
163does_implement_trait!(Clone => is_clone<T>);
164does_implement_trait!(Sized => is_sized<T>);
165does_implement_trait!(Unpin => is_unpin<T>);
166does_implement_trait!(ToString => is_to_string<T>);
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171 use std::{marker::PhantomPinned, rc::Rc};
172
173 struct Foo;
174
175 #[test]
176 fn test_does_implement_trait() {
177 assert!(is_send::<i32>());
178 assert!(!is_send::<Rc<i32>>());
179
180 assert!(is_sync::<i32>());
181 assert!(!is_sync::<Rc<i32>>());
182
183 assert!(is_copy::<i32>());
184 assert!(!is_copy::<Foo>());
185
186 assert!(is_clone::<i32>());
187 assert!(!is_clone::<Foo>());
188
189 assert!(is_sized::<[i32; 1]>());
190
191 assert!(is_unpin::<&i32>());
192 assert!(!is_unpin::<PhantomPinned>());
193
194 assert!(is_to_string::<i32>());
195 assert!(!is_to_string::<Foo>());
196 }
197}