summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--safe_libc/src/boxed.rs78
-rw-r--r--safe_libc/src/lib.rs3
-rw-r--r--safe_libc/src/string.rs36
-rw-r--r--src/main.rs5
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);
}