summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--rustfmt.toml1
-rw-r--r--safe_libc/src/boxed.rs150
-rw-r--r--safe_libc/src/errno.rs7
-rw-r--r--safe_libc/src/lib.rs7
-rw-r--r--safe_libc/src/stdio.rs17
-rw-r--r--safe_libc/src/string.rs72
-rw-r--r--safe_libc/src/util.rs13
-rw-r--r--src/main.rs17
-rw-r--r--src/system_alloc.rs21
9 files changed, 73 insertions, 232 deletions
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..218e203
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1 @@
+hard_tabs = true
diff --git a/safe_libc/src/boxed.rs b/safe_libc/src/boxed.rs
deleted file mode 100644
index 4a38b70..0000000
--- a/safe_libc/src/boxed.rs
+++ /dev/null
@@ -1,150 +0,0 @@
-use crate::util;
-
-use core::{fmt, mem, ptr};
-use core::ops::{Deref, DerefMut};
-
-fn alloc<T>(len: usize) -> *mut T {
- if util::zst::<T>(len) {
- return ptr::null_mut();
- }
- let size = len.checked_mul(mem::size_of::<T>()).expect("allocation overflow");
- let align = mem::align_of::<T>();
- util::must_succeed(
- unsafe {
- libc::memalign(align, size)
- }
- ).cast()
-}
-
-#[inline]
-const fn dangling<T>() -> *mut T {
- mem::align_of::<T>() as *mut T
-}
-
-#[inline]
-fn slice_len<T>(p: *const [T]) -> usize {
- unsafe { mem::transmute::<_, [usize; 2]>(p)[1] }
-}
-
-pub trait SafePtr {
- fn safe_ptr(p: *mut Self) -> *mut Self;
-}
-
-impl<T> SafePtr for T {
- #[inline]
- fn safe_ptr(p: *mut T) -> *mut T {
- if util::zst::<T>(1) {
- return dangling();
- }
-
- debug_assert!(!p.is_null(), "NULL ptr");
- p
- }
-}
-
-impl<T> SafePtr for [T] {
- #[inline]
- fn safe_ptr(p: *mut [T]) -> *mut [T] {
- let len = slice_len(p);
- if util::zst::<T>(len) {
- return ptr::slice_from_raw_parts_mut(dangling(), len);
- }
-
- debug_assert!(!p.is_null(), "NULL ptr");
- p
- }
-}
-
-pub struct CBox<T: SafePtr + ?Sized>(*mut T);
-
-impl<T: SafePtr + ?Sized> CBox<T> {
- #[inline]
- pub unsafe fn from_raw_unchecked(p: *mut T) -> CBox<T> {
- 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<T> CBox<T> {
- #[inline]
- pub fn new(value: T) -> CBox<T> {
- let p = alloc(1);
- unsafe {
- ptr::write(p, value);
- CBox::from_raw_unchecked(p)
- }
- }
-
- #[inline]
- pub unsafe fn from_raw(p: *mut T) -> CBox<T> {
- 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)
- }
-}
-
-impl<T: SafePtr + ?Sized> Drop for CBox<T> {
- #[inline]
- fn drop(&mut self) {
- unsafe {
- ptr::drop_in_place(self.0);
- libc::free(self.0.cast());
- }
- }
-}
-
-impl<T: SafePtr + ?Sized> Deref for CBox<T> {
- type Target = T;
-
- #[inline]
- fn deref(&self) -> &T {
- unsafe { &*T::safe_ptr(self.0) }
- }
-}
-
-impl<T: SafePtr + ?Sized> DerefMut for CBox<T> {
- #[inline]
- fn deref_mut(&mut self) -> &mut T {
- unsafe { &mut *T::safe_ptr(self.0) }
- }
-}
-
-impl<T: fmt::Debug + SafePtr + ?Sized> fmt::Debug for CBox<T> {
- #[inline]
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Debug::fmt(&**self, f)
- }
-}
-
-impl<T: fmt::Display + SafePtr + ?Sized> fmt::Display for CBox<T> {
- #[inline]
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Display::fmt(&**self, f)
- }
-}
diff --git a/safe_libc/src/errno.rs b/safe_libc/src/errno.rs
index be944d1..2a2220b 100644
--- a/safe_libc/src/errno.rs
+++ b/safe_libc/src/errno.rs
@@ -6,9 +6,14 @@ use core::fmt;
#[repr(transparent)]
pub struct Errno(pub libc::c_int);
+extern "C" {
+ //#[ffi_const]
+ pub fn __errno_location() -> *mut libc::c_int;
+}
+
#[inline]
pub fn errno() -> Errno {
- unsafe { Errno(*libc::__errno_location()) }
+ unsafe { Errno(*__errno_location()) }
}
impl fmt::Display for Errno {
diff --git a/safe_libc/src/lib.rs b/safe_libc/src/lib.rs
index aec5acc..6d9baf2 100644
--- a/safe_libc/src/lib.rs
+++ b/safe_libc/src/lib.rs
@@ -1,15 +1,18 @@
#![no_std]
+#![feature(slice_ptr_len)]
+#![feature(min_specialization)]
+// #![feature(ffi_const)]
+
+extern crate alloc;
pub use libc::*;
mod util;
-pub mod boxed;
pub mod errno;
pub mod stdio;
pub mod string;
-
extern "C" {
pub fn strndup(cs: *const libc::c_char, n: libc::size_t) -> *mut libc::c_char;
diff --git a/safe_libc/src/stdio.rs b/safe_libc/src/stdio.rs
index 2d19725..be016ab 100644
--- a/safe_libc/src/stdio.rs
+++ b/safe_libc/src/stdio.rs
@@ -41,28 +41,17 @@ pub fn stderr() -> Stderr {
impl BasicOStream {
#[inline]
pub fn flush(&mut self) -> Result<()> {
- check_io(unsafe {
- libc::fflush(self.0)
- } == 0)
+ check_io(unsafe { libc::fflush(self.0) } == 0)
}
#[inline]
pub fn write(&mut self, b: &[u8]) -> Result<()> {
- check_io(unsafe {
- libc::fwrite(
- b.as_ptr().cast(),
- 1,
- b.len(),
- self.0,
- )
- } == b.len())
+ check_io(unsafe { libc::fwrite(b.as_ptr().cast(), 1, b.len(), self.0) } == b.len())
}
#[inline]
pub fn puts(&mut self, s: &string::CStr) -> Result<()> {
- check_io(unsafe {
- libc::fputs(s.as_ptr(), self.0)
- } != libc::EOF)
+ check_io(unsafe { libc::fputs(s.as_ptr(), self.0) } != libc::EOF)
}
}
diff --git a/safe_libc/src/string.rs b/safe_libc/src/string.rs
index 53f8f87..6a8308a 100644
--- a/safe_libc/src/string.rs
+++ b/safe_libc/src/string.rs
@@ -1,39 +1,29 @@
-use crate::{self as libc, util, boxed::CBox};
+use crate::{self as libc, util};
-use core::slice;
-use core::ops::{Deref, DerefMut};
+use alloc::boxed::Box;
+use core::{ops::{Deref, DerefMut}, slice};
//pub struct FromBytesWithNulError {}
#[repr(transparent)]
-pub struct CStr { inner: libc::c_char }
+pub struct CStr {
+ inner: libc::c_char,
+}
impl CStr {
#[inline]
- pub unsafe fn from_ptr_unchecked<'a>(p: *const libc::c_char) -> &'a CStr {
- &*p.cast()
- }
-
- #[inline]
pub unsafe fn from_ptr<'a>(p: *const libc::c_char) -> &'a CStr {
- util::check_ptr(p, 1);
- CStr::from_ptr_unchecked(p)
- }
-
- #[inline]
- pub unsafe fn from_mut_ptr_unchecked<'a>(p: *mut libc::c_char) -> &'a mut CStr {
- &mut *p.cast()
+ &*p.cast()
}
#[inline]
pub unsafe fn from_mut_ptr<'a>(p: *mut libc::c_char) -> &'a mut CStr {
- util::check_ptr(p, 1);
- CStr::from_mut_ptr_unchecked(p)
+ &mut *p.cast()
}
#[inline]
pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
- CStr::from_ptr_unchecked(bytes.as_ptr().cast())
+ CStr::from_ptr(bytes.as_ptr().cast())
}
// TODO
@@ -57,18 +47,12 @@ impl CStr {
#[inline]
pub fn to_bytes(&self) -> &[u8] {
- unsafe { slice::from_raw_parts(
- self.as_ptr().cast(),
- self.len(),
- ) }
+ unsafe { slice::from_raw_parts(self.as_ptr().cast(), self.len()) }
}
#[inline]
pub fn to_mut_bytes(&mut self) -> &mut [u8] {
- unsafe { slice::from_raw_parts_mut(
- self.as_mut_ptr().cast(),
- self.len(),
- ) }
+ unsafe { slice::from_raw_parts_mut(self.as_mut_ptr().cast(), self.len()) }
}
#[inline]
@@ -89,28 +73,26 @@ impl CStr {
#[macro_export]
macro_rules! cstr {
- ($s:expr) => (
+ ($s:expr) => {
unsafe { $crate::string::CStr::from_bytes_with_nul_unchecked(concat!($s, "\0").as_bytes()) }
- )
+ };
}
-pub struct CString { inner: CBox<libc::c_char> }
+pub struct CString {
+ inner: Box<libc::c_char>,
+}
impl CString {
#[inline]
- pub unsafe fn from_raw_unchecked(p: *mut libc::c_char) -> CString {
- CString { inner: CBox::from_raw_unchecked(p) }
- }
-
- #[inline]
pub unsafe fn from_raw(p: *mut libc::c_char) -> CString {
- util::check_ptr(p, 1);
- CString::from_raw_unchecked(p)
+ CString {
+ inner: Box::from_raw(p),
+ }
}
#[inline]
pub fn into_raw(self) -> *mut libc::c_char {
- self.inner.into_raw()
+ Box::into_raw(self.inner)
}
}
@@ -133,12 +115,10 @@ impl DerefMut for CString {
impl From<&[u8]> for CString {
fn from(s: &[u8]) -> CString {
unsafe {
- CString::from_raw_unchecked(
- util::must_succeed(libc::strndup(
- s.as_ptr().cast(),
- s.len(),
- ))
- )
+ CString::from_raw(util::must_succeed(libc::strndup(
+ s.as_ptr().cast(),
+ s.len(),
+ )))
}
}
}
@@ -153,8 +133,6 @@ impl From<&str> for CString {
impl From<&CStr> for CString {
#[inline]
fn from(s: &CStr) -> CString {
- unsafe {
- CString::from_raw_unchecked(util::must_succeed(libc::strdup(s.as_ptr())))
- }
+ unsafe { CString::from_raw(util::must_succeed(libc::strdup(s.as_ptr()))) }
}
}
diff --git a/safe_libc/src/util.rs b/safe_libc/src/util.rs
index b8a4ed5..e91494e 100644
--- a/safe_libc/src/util.rs
+++ b/safe_libc/src/util.rs
@@ -1,16 +1,3 @@
-use core::mem;
-
-#[inline]
-pub fn zst<T>(len: usize) -> bool {
- mem::size_of::<T>() == 0 || len == 0
-}
-
-#[inline]
-pub fn check_ptr<T>(p: *const T, len: usize) {
- debug_assert!((p as usize) % mem::align_of::<T>() == 0, "unaligned ptr");
- assert!(zst::<T>(len) || !p.is_null(), "NULL ptr");
-}
-
#[inline]
pub fn must_succeed<T>(p: *mut T) -> *mut T {
assert!(!p.is_null(), "allocation failure");
diff --git a/src/main.rs b/src/main.rs
index 26882ff..fe151fe 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,8 +1,12 @@
#![no_main]
#![no_std]
+#![feature(alloc_error_handler)]
-use safe_libc as libc;
+mod system_alloc;
+
+extern crate alloc;
use libc::cstr;
+use safe_libc as libc;
use core::fmt::Write;
@@ -19,17 +23,20 @@ pub extern "C" fn main(_nargs: libc::c_int, _args: *const *const libc::c_char) -
let x = libc::string::CString::from("foo");
let l = x.len();
let y = x.into_raw();
- let z = unsafe {
- libc::boxed::CBox::slice_from_raw_parts(y, l)
- };
+ let z = unsafe { alloc::boxed::Box::from_raw(core::ptr::slice_from_raw_parts_mut(y, l)) };
let _ = writeln!(stdout, "Foo: {} {} {}", z[0], z[1], z[2]);
}
{
- let b = libc::boxed::CBox::new(42);
+ let b = alloc::boxed::Box::new(42);
let _ = writeln!(stdout, "Bar: {}", b);
}
+ {
+ let x = alloc::boxed::Box::new(());
+ let _ = writeln!(stdout, "Box: {:?}", x);
+ }
+
0
}
diff --git a/src/system_alloc.rs b/src/system_alloc.rs
new file mode 100644
index 0000000..ad1afcb
--- /dev/null
+++ b/src/system_alloc.rs
@@ -0,0 +1,21 @@
+use safe_libc as libc;
+
+struct System;
+
+unsafe impl alloc::alloc::GlobalAlloc for System {
+ unsafe fn alloc(&self, layout: alloc::alloc::Layout) -> *mut u8 {
+ libc::memalign(layout.align(), layout.size()).cast()
+ }
+
+ unsafe fn dealloc(&self, ptr: *mut u8, _layout: alloc::alloc::Layout) {
+ libc::free(ptr.cast());
+ }
+}
+
+#[global_allocator]
+static SYSTEM_ALLOC: System = System;
+
+#[alloc_error_handler]
+fn alloc_error(_: core::alloc::Layout) -> ! {
+ panic!("allocation failure");
+}