Introduce SafePtr trait, cleanup
This commit is contained in:
parent
de9bc974a6
commit
fff906a78b
2 changed files with 60 additions and 75 deletions
|
@ -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)
|
||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -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 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 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);
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue