Skip to main content

value_box/
erased.rs

1use std::any::Any;
2use std::ffi::c_void;
3use std::mem::size_of;
4use std::ptr::NonNull;
5
6use crate::{BoxerError, Result};
7
8#[repr(transparent)]
9pub struct ErasedBorrowedPtr {
10    ptr: *mut c_void,
11}
12
13impl ErasedBorrowedPtr {
14    /// # Safety
15    ///
16    /// `ptr` must be either null or point to a valid value for the duration of
17    /// any pointer-based operations performed through this wrapper.
18    pub const unsafe fn from_raw(ptr: *mut c_void) -> Self {
19        Self { ptr }
20    }
21
22    pub const fn null() -> Self {
23        Self {
24            ptr: std::ptr::null_mut(),
25        }
26    }
27
28    pub const fn as_raw(&self) -> *mut c_void {
29        self.ptr
30    }
31
32    pub fn is_null(&self) -> bool {
33        self.ptr.is_null()
34    }
35
36    pub fn with_ptr<R: Any, F>(&self, op: F) -> Result<R>
37    where
38        F: FnOnce(NonNull<c_void>) -> Result<R>,
39    {
40        let pointer = NonNull::new(self.ptr)
41            .ok_or_else(|| BoxerError::NullPointer("erased borrowed ptr".to_string()))?;
42        op(pointer)
43    }
44
45    pub fn with_ptr_ok<R: Any, F>(&self, op: F) -> Result<R>
46    where
47        F: FnOnce(NonNull<c_void>) -> R,
48    {
49        self.with_ptr(|pointer| Ok(op(pointer)))
50    }
51}
52
53impl Default for ErasedBorrowedPtr {
54    fn default() -> Self {
55        Self::null()
56    }
57}
58
59/// Tell Rust to take back the control over memory.
60///
61/// # Safety
62///
63/// `pointer` must come from [`Box::into_raw`] for the same `T`, must not be
64/// null, and must not have already been reclaimed.
65pub unsafe fn from_raw<T>(pointer: *mut T) -> Box<T> {
66    assert!(!pointer.is_null(), "from_raw(): Pointer must not be null!");
67    assert_eq!(
68        size_of::<*mut T>(),
69        size_of::<*mut c_void>(),
70        "The pointer must be compatible with void*"
71    );
72    unsafe { Box::from_raw(pointer) }
73}
74
75pub fn into_raw<T>(boxed: Box<T>) -> *mut T {
76    assert_eq!(
77        size_of::<*mut T>(),
78        size_of::<*mut c_void>(),
79        "The pointer must be compatible with void*"
80    );
81    Box::into_raw(boxed)
82}