From f0b3d5166ef1255fac880b146875ef46d2599a13 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 4 Apr 2020 13:22:18 +0200 Subject: Reorganize --- safe_libc/src/boxed.rs | 146 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 safe_libc/src/boxed.rs (limited to 'safe_libc/src/boxed.rs') diff --git a/safe_libc/src/boxed.rs b/safe_libc/src/boxed.rs new file mode 100644 index 0000000..72c961c --- /dev/null +++ b/safe_libc/src/boxed.rs @@ -0,0 +1,146 @@ +use crate::util; + +use core::{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) as *mut T + } + ) +} + +#[inline] +fn dangling() -> *mut T { + mem::align_of::() as *mut T +} + +#[inline] +fn slice_len(p: *const [T]) -> usize { + unsafe { mem::transmute::<*const [T], [usize; 2]>(p)[1] } +} + +pub struct CBox(*mut T); + +impl CBox { + #[inline] + pub 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 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 as *mut libc::c_void); + } + } +} + +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() } + } +} -- cgit v1.2.3