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] }
|
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]
|
#[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)
|
CBox(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +71,7 @@ impl<T: ?Sized> CBox<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn as_ptr(&self) -> *const T {
|
pub fn as_ptr(&self) -> *const T {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,32 +107,9 @@ impl<T> CBox<T> {
|
||||||
util::check_ptr(p, len);
|
util::check_ptr(p, len);
|
||||||
CBox::slice_from_raw_parts_unchecked(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]> {
|
impl<T: SafePtr + ?Sized> Drop for 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> {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
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;
|
type Target = T;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deref(&self) -> &T {
|
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]
|
#[inline]
|
||||||
fn deref_mut(&mut self) -> &mut T {
|
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]> {
|
impl<T: fmt::Debug + SafePtr + ?Sized> fmt::Debug 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> {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt::Debug::fmt(&**self, f)
|
fmt::Debug::fmt(&**self, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> fmt::Debug for CBox<[T]> where [T]: fmt::Debug {
|
impl<T: fmt::Display + SafePtr + ?Sized> fmt::Display for CBox<T> {
|
||||||
#[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 {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt::Display::fmt(&**self, f)
|
fmt::Display::fmt(&**self, f)
|
||||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -9,17 +9,26 @@ use core::fmt::Write;
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn main(_nargs: libc::c_int, _args: *const *const libc::c_char) -> libc::c_int {
|
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 mut stdout = unsafe { libc::stdio::stdout() };
|
||||||
|
|
||||||
|
{
|
||||||
|
let foo = cstr!("Foo!\n");
|
||||||
|
stdout.puts(foo);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
let x = libc::string::CString::from("foo");
|
let x = libc::string::CString::from("foo");
|
||||||
let l = x.len();
|
let l = x.len();
|
||||||
let y = x.into_raw();
|
let y = x.into_raw();
|
||||||
let z = unsafe {
|
let z = unsafe {
|
||||||
libc::boxed::CBox::slice_from_raw_parts(y, l)
|
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 _ = writeln!(stdout, "Foo: {} {} {}", z[0], z[1], z[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
let b = libc::boxed::CBox::new(42);
|
let b = libc::boxed::CBox::new(42);
|
||||||
let _ = writeln!(stdout, "Bar: {}", b);
|
let _ = writeln!(stdout, "Bar: {}", b);
|
||||||
|
}
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue