intuicio_data/
lib.rs

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