Use extern type for CStr
This commit is contained in:
parent
fd2384b7fa
commit
a205bbb1d2
4 changed files with 105 additions and 17 deletions
78
safe_libc/src/boxed.rs
Normal file
78
safe_libc/src/boxed.rs
Normal 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>;
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Reference in a new issue