Introduce SafePtr trait, cleanup

This commit is contained in:
Matthias Schiffer 2020-04-05 14:22:59 +02:00
parent de9bc974a6
commit fff906a78b
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C
2 changed files with 60 additions and 75 deletions

View file

@ -26,11 +26,40 @@ fn slice_len<T>(p: *const [T]) -> usize {
unsafe { mem::transmute::<_, [usize; 2]>(p)[1] }
}
pub struct CBox<T: ?Sized>(*mut T);
pub trait SafePtr {
fn safe_ptr(p: *mut Self) -> *mut Self;
}
impl<T: ?Sized> CBox<T> {
impl<T> SafePtr for T {
#[inline]
pub const unsafe fn from_raw_unchecked(p: *mut T) -> CBox<T> {
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)
}
@ -42,7 +71,7 @@ impl<T: ?Sized> CBox<T> {
}
#[inline]
pub const fn as_ptr(&self) -> *const T {
pub fn as_ptr(&self) -> *const T {
self.0
}
@ -78,32 +107,9 @@ impl<T> CBox<T> {
util::check_ptr(p, len);
CBox::slice_from_raw_parts_unchecked(p, len)
}
#[inline]
fn safe_ptr(&self) -> *mut T {
if util::zst::<T>(1) {
return dangling();
}
debug_assert!(!self.0.is_null(), "NULL ptr");
self.0
}
}
impl<T> CBox<[T]> {
#[inline]
fn safe_ptr(&self) -> *mut [T] {
if self.0.is_null() {
let len = slice_len(self.0);
debug_assert!(util::zst::<T>(len), "NULL ptr");
return ptr::slice_from_raw_parts_mut(dangling(), len);
}
self.0
}
}
impl<T: ?Sized> Drop for CBox<T> {
impl<T: SafePtr + ?Sized> Drop for CBox<T> {
#[inline]
fn drop(&mut self) {
unsafe {
@ -113,60 +119,30 @@ impl<T: ?Sized> Drop for CBox<T> {
}
}
impl<T> Deref for CBox<T> {
impl<T: SafePtr + ?Sized> Deref for CBox<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { &*self.safe_ptr() }
unsafe { &*T::safe_ptr(self.0) }
}
}
impl<T> DerefMut for CBox<T> {
impl<T: SafePtr + ?Sized> DerefMut for CBox<T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.safe_ptr() }
unsafe { &mut *T::safe_ptr(self.0) }
}
}
impl<T> Deref for CBox<[T]> {
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
unsafe { &*self.safe_ptr() }
}
}
impl<T> DerefMut for CBox<[T]> {
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
unsafe { &mut *self.safe_ptr() }
}
}
impl<T: fmt::Debug> fmt::Debug for CBox<T> {
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::Debug for CBox<[T]> where [T]: fmt::Debug {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: fmt::Display> fmt::Display for CBox<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T> fmt::Display for CBox<[T]> where [T]: fmt::Display {
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)

View file

@ -9,17 +9,26 @@ use core::fmt::Write;
#[no_mangle]
pub extern "C" fn main(_nargs: libc::c_int, _args: *const *const libc::c_char) -> libc::c_int {
let mut stdout = unsafe { libc::stdio::stdout() };
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 foo = cstr!("Foo!\n");
stdout.puts(foo);
let _ = writeln!(stdout, "Foo: {} {} {}", z[0], z[1], z[2]);
let b = libc::boxed::CBox::new(42);
let _ = writeln!(stdout, "Bar: {}", b);
{
let foo = cstr!("Foo!\n");
stdout.puts(foo);
}
{
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 _ = writeln!(stdout, "Foo: {} {} {}", z[0], z[1], z[2]);
}
{
let b = libc::boxed::CBox::new(42);
let _ = writeln!(stdout, "Bar: {}", b);
}
0
}