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 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    /// # Safety
19    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    /// # Safety
35    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
51/// # Safety
52pub 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
69/// # Safety
70pub 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
86/// # Safety
87pub 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
109/// # Safety
110pub 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}