boltffi_core 0.22.0

Core runtime types for BoltFFI - high-performance FFI bindings generator
Documentation
use std::ptr::NonNull;

pub struct HandleBox<T> {
    ptr: NonNull<T>,
}

impl<T> HandleBox<T> {
    pub fn new(value: T) -> Self {
        let boxed = Box::new(value);
        Self {
            ptr: unsafe { NonNull::new_unchecked(Box::into_raw(boxed)) },
        }
    }

    pub fn into_raw(self) -> *mut T {
        let ptr = self.ptr.as_ptr();
        core::mem::forget(self);
        ptr
    }

    pub unsafe fn from_raw(ptr: *mut T) -> Option<Self> {
        NonNull::new(ptr).map(|ptr| Self { ptr })
    }
}

impl<T> AsRef<T> for HandleBox<T> {
    fn as_ref(&self) -> &T {
        unsafe { self.ptr.as_ref() }
    }
}

impl<T> AsMut<T> for HandleBox<T> {
    fn as_mut(&mut self) -> &mut T {
        unsafe { self.ptr.as_mut() }
    }
}

impl<T> Drop for HandleBox<T> {
    fn drop(&mut self) {
        unsafe {
            let _ = Box::from_raw(self.ptr.as_ptr());
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn handle_roundtrip() {
        let handle = HandleBox::new(42u32);
        let ptr = handle.into_raw();
        let recovered = unsafe { HandleBox::from_raw(ptr) }.unwrap();
        assert_eq!(*recovered.as_ref(), 42);
    }

    #[test]
    fn handle_null() {
        let result: Option<HandleBox<u32>> = unsafe { HandleBox::from_raw(core::ptr::null_mut()) };
        assert!(result.is_none());
    }
}