Use extern type for CStr

This commit is contained in:
Matthias Schiffer 2020-05-01 22:21:17 +02:00
parent fd2384b7fa
commit a205bbb1d2
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C
4 changed files with 105 additions and 17 deletions

78
safe_libc/src/boxed.rs Normal file
View file

@ -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>;

View file

@ -1,6 +1,6 @@
#![no_std] #![no_std]
#![feature(extern_types)]
#![feature(slice_ptr_len)] #![feature(slice_ptr_len)]
#![feature(min_specialization)]
// #![feature(ffi_const)] // #![feature(ffi_const)]
extern crate alloc; extern crate alloc;
@ -9,6 +9,7 @@ pub use libc::*;
mod util; mod util;
pub mod boxed;
pub mod errno; pub mod errno;
pub mod stdio; pub mod stdio;
pub mod string; pub mod string;

View file

@ -1,24 +1,26 @@
use crate::{self as libc, util}; use crate::{self as libc, boxed::CBox, util};
use alloc::boxed::Box; use core::{mem, slice};
use core::{ops::{Deref, DerefMut}, slice}; use core::ops::{Deref, DerefMut};
//pub struct FromBytesWithNulError {} //pub struct FromBytesWithNulError {}
#[repr(transparent)] extern "C" {
pub struct CStr { type RawCStr;
inner: libc::c_char,
} }
#[repr(transparent)]
pub struct CStr(RawCStr);
impl CStr { impl CStr {
#[inline] #[inline]
pub unsafe fn from_ptr<'a>(p: *const libc::c_char) -> &'a CStr { pub unsafe fn from_ptr<'a>(p: *const libc::c_char) -> &'a CStr {
&*p.cast() &*(p as *const CStr)
} }
#[inline] #[inline]
pub unsafe fn from_mut_ptr<'a>(p: *mut libc::c_char) -> &'a mut CStr { pub unsafe fn from_mut_ptr<'a>(p: *mut libc::c_char) -> &'a mut CStr {
&mut *p.cast() &mut *(p as *mut CStr)
} }
#[inline] #[inline]
@ -37,12 +39,12 @@ impl CStr {
#[inline] #[inline]
pub const fn as_ptr(&self) -> *const libc::c_char { pub const fn as_ptr(&self) -> *const libc::c_char {
&self.inner (self as *const CStr).cast()
} }
#[inline] #[inline]
pub fn as_mut_ptr(&mut self) -> *mut libc::c_char { pub fn as_mut_ptr(&mut self) -> *mut libc::c_char {
&mut self.inner (self as *mut CStr).cast()
} }
#[inline] #[inline]
@ -79,20 +81,22 @@ macro_rules! cstr {
} }
pub struct CString { pub struct CString {
inner: Box<libc::c_char>, inner: CBox<CStr>,
} }
impl CString { impl CString {
#[inline] #[inline]
pub unsafe fn from_raw(p: *mut libc::c_char) -> CString { pub unsafe fn from_raw(p: *mut libc::c_char) -> CString {
CString { CString {
inner: Box::from_raw(p), inner: CBox::from_raw_unchecked(p as *mut CStr)
} }
} }
#[inline] #[inline]
pub fn into_raw(self) -> *mut libc::c_char { pub fn into_raw(mut self) -> *mut libc::c_char {
Box::into_raw(self.inner) let p = self.as_mut_ptr();
mem::forget(self);
p
} }
} }
@ -101,14 +105,14 @@ impl Deref for CString {
#[inline] #[inline]
fn deref(&self) -> &CStr { fn deref(&self) -> &CStr {
unsafe { CStr::from_ptr(&*self.inner) } &*self.inner
} }
} }
impl DerefMut for CString { impl DerefMut for CString {
#[inline] #[inline]
fn deref_mut(&mut self) -> &mut CStr { fn deref_mut(&mut self) -> &mut CStr {
unsafe { CStr::from_mut_ptr(&mut *self.inner) } &mut *self.inner
} }
} }

View file

@ -27,6 +27,11 @@ pub extern "C" fn main(_nargs: libc::c_int, _args: *const *const libc::c_char) -
let _ = writeln!(stdout, "Foo: {} {} {}", z[0], z[1], z[2]); let _ = writeln!(stdout, "Foo: {} {} {}", z[0], z[1], z[2]);
} }
{
let x = libc::string::CString::from("bar");
let _ = stdout.puts(&x);
}
{ {
let b = alloc::boxed::Box::new(42); let b = alloc::boxed::Box::new(42);
let _ = writeln!(stdout, "Bar: {}", b); let _ = writeln!(stdout, "Bar: {}", b);