memkit 0.2.0-beta.1

Deterministic, intent-driven memory allocation for systems requiring predictable performance
Documentation
//! Heap-allocated box type.

use std::ops::{Deref, DerefMut};
use std::ptr::NonNull;

/// A Box-like wrapper for heap-allocated memory.
///
/// Automatically frees memory when dropped.
pub struct MkHeapBox<T> {
    ptr: NonNull<T>,
}

impl<T> MkHeapBox<T> {
    /// Create a new MkHeapBox.
    ///
    /// # Safety
    ///
    /// The pointer must have been allocated from the heap.
    pub(crate) unsafe fn from_raw(ptr: *mut T) -> Option<Self> {
        NonNull::new(ptr).map(|ptr| Self { ptr })
    }

    /// Get the raw pointer.
    pub fn as_ptr(&self) -> *const T {
        self.ptr.as_ptr()
    }

    /// Get the raw mutable pointer.
    pub fn as_mut_ptr(&mut self) -> *mut T {
        self.ptr.as_ptr()
    }

    /// Leak the MkHeapBox, returning the raw pointer.
    pub fn into_raw(self) -> *mut T {
        let ptr = self.ptr.as_ptr();
        std::mem::forget(self);
        ptr
    }
}

impl<T> Deref for MkHeapBox<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        unsafe { self.ptr.as_ref() }
    }
}

impl<T> DerefMut for MkHeapBox<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { self.ptr.as_mut() }
    }
}

impl<T> Drop for MkHeapBox<T> {
    fn drop(&mut self) {
        unsafe {
            // Drop the value
            std::ptr::drop_in_place(self.ptr.as_ptr());
            // Free the memory
            let layout = std::alloc::Layout::new::<T>();
            std::alloc::dealloc(self.ptr.as_ptr() as *mut u8, layout);
        }
    }
}

unsafe impl<T: Send> Send for MkHeapBox<T> {}
unsafe impl<T: Sync> Sync for MkHeapBox<T> {}