ffi_types/
boxed.rs

1/// A type alias for `std::boxed::Box<T>`.
2///
3/// `Box` doesn't require a wrapper because it is guaranteed to be layout as a pointer.
4pub type Box<T> = std::boxed::Box<T>;
5
6/// A type alias for `Option<Box<T>>`.
7///
8/// `None` value means a null pointer.
9#[repr(C)]
10pub struct OptionBox<T> {
11    pub ptr: *mut T,
12}
13static_assertions::assert_eq_size!(OptionBox<u8>, *const u8);
14static_assertions::assert_eq_size!(OptionBox<u8>, Box<u8>);
15static_assertions::assert_eq_size!(OptionBox<u8>, Option<Box<u8>>);
16
17impl<T> std::fmt::Debug for OptionBox<T>
18where
19    T: 'static + std::fmt::Debug,
20{
21    #[inline(always)]
22    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23        unsafe { self.ptr.as_ref().fmt(f) }
24    }
25}
26
27impl<T> Clone for OptionBox<T>
28where
29    T: 'static + Clone,
30{
31    #[inline(always)]
32    fn clone(&self) -> Self {
33        if self.ptr.is_null() {
34            return Self::none();
35        }
36        let borrowed_box = unsafe { Box::from_raw(self.ptr) };
37        let cloned = borrowed_box.clone();
38        std::mem::forget(borrowed_box);
39        cloned.into()
40    }
41}
42
43impl<T> Drop for OptionBox<T> {
44    #[inline(always)]
45    fn drop(&mut self) {
46        if !self.ptr.is_null() {
47            drop(unsafe { Box::from_raw(self.ptr) });
48        }
49    }
50}
51
52impl<T> OptionBox<T> {
53    #[inline(always)]
54    pub fn new(boxed: Box<T>) -> Self {
55        Self {
56            ptr: Box::into_raw(boxed),
57        }
58    }
59
60    #[inline(always)]
61    pub fn from_value(value: T) -> Self {
62        Self::new(Box::new(value))
63    }
64
65    #[inline(always)]
66    pub fn into_box(self) -> Option<Box<T>> {
67        if self.ptr.is_null() {
68            return None;
69        }
70        Some(unsafe { Box::from_raw(self.ptr) })
71    }
72
73    #[inline(always)]
74    pub const fn none() -> Self {
75        Self {
76            ptr: std::ptr::null_mut(),
77        }
78    }
79
80    #[inline]
81    pub fn as_ref(&self) -> Option<&T> {
82        unsafe { self.ptr.as_ref() } // SAFETY: `ptr` is a value of a valid Box
83    }
84}
85
86impl<T> From<Box<T>> for OptionBox<T> {
87    #[inline]
88    fn from(boxed: Box<T>) -> Self {
89        Self::new(boxed)
90    }
91}
92
93impl<T> From<Option<Box<T>>> for OptionBox<T> {
94    #[inline]
95    fn from(boxed: Option<Box<T>>) -> Self {
96        if let Some(boxed) = boxed {
97            Self::new(boxed)
98        } else {
99            Self::none()
100        }
101    }
102}
103
104impl<T> Default for OptionBox<T> {
105    #[inline(always)]
106    fn default() -> Self {
107        Self::none()
108    }
109}
110
111// impl<T> std::convert::AsRef<Option<Box<T>>> for OptionBox<T> {
112//     #[inline(always)]
113//     fn as_ref(&self) -> &Option<Box<T>> {
114//         &self.0
115//     }
116// }
117
118// impl<T> std::borrow::Borrow<Option<Box<T>>> for OptionBox<T> {
119//     #[inline(always)]
120//     fn borrow(&self) -> &Option<Box<T>> {
121//         self.as_ref()
122//     }
123// }
124
125// impl<T> std::ops::Deref for OptionBox<T> {
126//     type Target = Option<Box<T>>;
127
128//     #[inline(always)]
129//     fn deref(&self) -> &Self::Target {
130//         self.as_ref()
131//     }
132// }