use crate::util; use core::{fmt, mem, ptr}; use core::ops::{Deref, DerefMut}; fn alloc(len: usize) -> *mut T { if util::zst::(len) { return ptr::null_mut(); } let size = len.checked_mul(mem::size_of::()).expect("allocation overflow"); let align = mem::align_of::(); util::must_succeed( unsafe { libc::memalign(align as libc::size_t, size as libc::size_t) } ).cast() } #[inline] const fn dangling() -> *mut T { mem::align_of::() as *mut T } #[inline] fn slice_len(p: *const [T]) -> usize { unsafe { mem::transmute::<_, [usize; 2]>(p)[1] } } pub struct CBox(*mut T); impl CBox { #[inline] pub const unsafe fn from_raw_unchecked(p: *mut T) -> CBox { CBox(p) } #[inline] pub fn into_raw(self) -> *mut T { let p = self.0; mem::forget(self); p } #[inline] pub const fn as_ptr(&self) -> *const T { self.0 } #[inline] pub fn as_mut_ptr(&mut self) -> *mut T { self.0 } } impl CBox { #[inline] pub fn new(value: T) -> CBox { let p = alloc(1); unsafe { ptr::write(p, value); CBox::from_raw_unchecked(p) } } #[inline] pub unsafe fn from_raw(p: *mut T) -> CBox { util::check_ptr(p, 1); CBox(p) } #[inline] pub unsafe fn slice_from_raw_parts_unchecked(p: *mut T, len: usize) -> CBox<[T]> { CBox(ptr::slice_from_raw_parts_mut(p, len)) } #[inline] pub unsafe fn slice_from_raw_parts(p: *mut T, len: usize) -> CBox<[T]> { util::check_ptr(p, len); CBox::slice_from_raw_parts_unchecked(p, len) } #[inline] fn safe_ptr(&self) -> *mut T { if util::zst::(1) { return dangling(); } debug_assert!(!self.0.is_null(), "NULL ptr"); self.0 } } impl CBox<[T]> { #[inline] fn safe_ptr(&self) -> *mut [T] { if self.0.is_null() { let len = slice_len(self.0); debug_assert!(util::zst::(len), "NULL ptr"); return ptr::slice_from_raw_parts_mut(dangling(), len); } self.0 } } impl Drop for CBox { #[inline] fn drop(&mut self) { unsafe { ptr::drop_in_place(self.0); libc::free(self.0.cast()); } } } impl Deref for CBox { type Target = T; #[inline] fn deref(&self) -> &T { unsafe { &*self.safe_ptr() } } } impl DerefMut for CBox { #[inline] fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.safe_ptr() } } } impl Deref for CBox<[T]> { type Target = [T]; #[inline] fn deref(&self) -> &[T] { unsafe { &*self.safe_ptr() } } } impl DerefMut for CBox<[T]> { #[inline] fn deref_mut(&mut self) -> &mut [T] { unsafe { &mut *self.safe_ptr() } } } impl fmt::Debug for CBox { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } impl fmt::Debug for CBox<[T]> where [T]: fmt::Debug { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } impl fmt::Display for CBox { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&**self, f) } } impl fmt::Display for CBox<[T]> where [T]: fmt::Display { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&**self, f) } }