intuicio_data/
lib.rs

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