diff options
-rw-r--r-- | safe_libc/src/boxed.rs | 78 | ||||
-rw-r--r-- | safe_libc/src/lib.rs | 3 | ||||
-rw-r--r-- | safe_libc/src/string.rs | 36 | ||||
-rw-r--r-- | src/main.rs | 5 |
4 files changed, 105 insertions, 17 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>; diff --git a/safe_libc/src/lib.rs b/safe_libc/src/lib.rs index 6d9baf2..2e39b8d 100644 --- a/safe_libc/src/lib.rs +++ b/safe_libc/src/lib.rs @@ -1,6 +1,6 @@ #![no_std] +#![feature(extern_types)] #![feature(slice_ptr_len)] -#![feature(min_specialization)] // #![feature(ffi_const)] extern crate alloc; @@ -9,6 +9,7 @@ pub use libc::*; mod util; +pub mod boxed; pub mod errno; pub mod stdio; pub mod string; diff --git a/safe_libc/src/string.rs b/safe_libc/src/string.rs index 6a8308a..5483e08 100644 --- a/safe_libc/src/string.rs +++ b/safe_libc/src/string.rs @@ -1,24 +1,26 @@ -use crate::{self as libc, util}; +use crate::{self as libc, boxed::CBox, util}; -use alloc::boxed::Box; -use core::{ops::{Deref, DerefMut}, slice}; +use core::{mem, slice}; +use core::ops::{Deref, DerefMut}; //pub struct FromBytesWithNulError {} -#[repr(transparent)] -pub struct CStr { - inner: libc::c_char, +extern "C" { + type RawCStr; } +#[repr(transparent)] +pub struct CStr(RawCStr); + impl CStr { #[inline] pub unsafe fn from_ptr<'a>(p: *const libc::c_char) -> &'a CStr { - &*p.cast() + &*(p as *const CStr) } #[inline] pub unsafe fn from_mut_ptr<'a>(p: *mut libc::c_char) -> &'a mut CStr { - &mut *p.cast() + &mut *(p as *mut CStr) } #[inline] @@ -37,12 +39,12 @@ impl CStr { #[inline] pub const fn as_ptr(&self) -> *const libc::c_char { - &self.inner + (self as *const CStr).cast() } #[inline] pub fn as_mut_ptr(&mut self) -> *mut libc::c_char { - &mut self.inner + (self as *mut CStr).cast() } #[inline] @@ -79,20 +81,22 @@ macro_rules! cstr { } pub struct CString { - inner: Box<libc::c_char>, + inner: CBox<CStr>, } impl CString { #[inline] pub unsafe fn from_raw(p: *mut libc::c_char) -> CString { CString { - inner: Box::from_raw(p), + inner: CBox::from_raw_unchecked(p as *mut CStr) } } #[inline] - pub fn into_raw(self) -> *mut libc::c_char { - Box::into_raw(self.inner) + pub fn into_raw(mut self) -> *mut libc::c_char { + let p = self.as_mut_ptr(); + mem::forget(self); + p } } @@ -101,14 +105,14 @@ impl Deref for CString { #[inline] fn deref(&self) -> &CStr { - unsafe { CStr::from_ptr(&*self.inner) } + &*self.inner } } impl DerefMut for CString { #[inline] fn deref_mut(&mut self) -> &mut CStr { - unsafe { CStr::from_mut_ptr(&mut *self.inner) } + &mut *self.inner } } diff --git a/src/main.rs b/src/main.rs index fe151fe..c6ec961 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,6 +28,11 @@ pub extern "C" fn main(_nargs: libc::c_int, _args: *const *const libc::c_char) - } { + let x = libc::string::CString::from("bar"); + let _ = stdout.puts(&x); + } + + { let b = alloc::boxed::Box::new(42); let _ = writeln!(stdout, "Bar: {}", b); } |