summaryrefslogtreecommitdiffstats
path: root/safe_libc/src/boxed.rs
diff options
context:
space:
mode:
Diffstat (limited to 'safe_libc/src/boxed.rs')
-rw-r--r--safe_libc/src/boxed.rs78
1 files changed, 78 insertions, 0 deletions
diff --git a/safe_libc/src/boxed.rs b/safe_libc/src/boxed.rs
new file mode 100644
index 0000000..a0bbfb4
--- /dev/null
+++ b/safe_libc/src/boxed.rs
@@ -0,0 +1,78 @@
+use core::{marker, mem, ptr};
+use core::ops::{Deref, DerefMut};
+
+pub trait Dealloc<T: ?Sized> {
+ unsafe fn dealloc(p: *mut T);
+}
+
+#[repr(transparent)]
+pub struct BoxLike<T: ?Sized, D: Dealloc<T>> {
+ inner: ptr::NonNull<T>,
+ _phantom: marker::PhantomData<T>,
+ _dropper: marker::PhantomData<D>,
+}
+
+impl<T: ?Sized, D: Dealloc<T>> BoxLike<T, D> {
+ #[inline]
+ pub unsafe fn from_raw_unchecked(p: *mut T) -> Self {
+ BoxLike {
+ inner: ptr::NonNull::new_unchecked(p),
+ _phantom: marker::PhantomData,
+ _dropper: marker::PhantomData,
+ }
+ }
+
+ #[inline]
+ pub unsafe fn from_raw(p: *mut T) -> Option<Self> {
+ if p.is_null() {
+ None
+ } else {
+ Some(Self::from_raw_unchecked(p))
+ }
+ }
+
+ #[inline]
+ pub fn into_raw(self) -> *mut T {
+ let p = self.inner.as_ptr();
+ mem::forget(self);
+ p
+ }
+}
+
+impl<T: ?Sized, D: Dealloc<T>> Drop for BoxLike<T, D> {
+ #[inline]
+ fn drop(&mut self) {
+ let p = self.inner.as_ptr();
+ unsafe {
+ ptr::drop_in_place(p);
+ D::dealloc(p);
+ }
+ }
+}
+
+impl<T: ?Sized, D: Dealloc<T>> Deref for BoxLike<T, D> {
+ type Target = T;
+
+ #[inline]
+ fn deref(&self) -> &T {
+ unsafe { self.inner.as_ref() }
+ }
+}
+
+impl<T: ?Sized, D: Dealloc<T>> DerefMut for BoxLike<T, D> {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut T {
+ unsafe { self.inner.as_mut() }
+ }
+}
+
+pub struct DeallocFree;
+
+impl<T: ?Sized> Dealloc<T> for DeallocFree {
+ #[inline]
+ unsafe fn dealloc(p: *mut T) {
+ libc::free(p as _);
+ }
+}
+
+pub type CBox<T> = BoxLike<T, DeallocFree>;