intuicio_data/
lib.rs

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