diff --git a/src/bad_things.rs b/src/bad_things.rs new file mode 100644 index 0000000..d5bc526 --- /dev/null +++ b/src/bad_things.rs @@ -0,0 +1,50 @@ +// use std::{fmt::Debug, intrinsics::transmute, mem::{transmute_copy, MaybeUninit, ManuallyDrop}, alloc::{dealloc, Layout}, ptr::drop_in_place}; + +// trait IsSized { +// type SizedRepr; + +// fn is_sized() -> bool; +// } + +// impl IsSized for T { +// default type SizedRepr = Box; + +// default fn is_sized() -> bool { +// false +// } +// } + +// impl IsSized for T { +// type SizedRepr = T; + +// fn is_sized() -> bool { +// true +// } +// } + +// #[repr(transparent)] +// struct Item(::SizedRepr); + +// impl Item { +// fn from_box(v: Box) -> Self { +// let ret = if T::is_sized() { +// // SAFETY: #[repr(transparent)], and we know its `SizedRepr` is just `T` +// unsafe { (&*v as *const _ as *const Self).read() } +// let ptr = Box::into_raw(v); +// unsafe { dealloc(ptr.cast(), Layout::for_value_raw(ptr)) } +// } else { +// // SAFETY: #[repr(transparent)], and we know its `SizedRepr` is `Box` +// unsafe { (&v as *const _ as *const Self).read() } +// mem::forget(v); +// }; + +// ret +// } +// } + +// #[test] +// pub fn testing() { +// dbg!(usize::is_sized()); +// dbg!(::is_sized()); +// } + diff --git a/src/ptr_ext.rs b/src/ptr_ext.rs new file mode 100644 index 0000000..5537f62 --- /dev/null +++ b/src/ptr_ext.rs @@ -0,0 +1,170 @@ +use std::{ptr::{self, Pointee}, mem::size_of_val_raw, alloc::{alloc, Layout}}; + +use self::__priv::Sealed; + +mod __priv { + pub trait Sealed {} + + impl Sealed for *const T {} + impl Sealed for *mut T {} +} + +pub trait PtrExt: Sealed { + type Pointee: ?Sized; + + fn addr(self) -> usize; + + fn align_up(self, align: usize) -> Self; + + fn with_addr_from(self, addr: *const U) -> Self; + + fn with_addr(self, addr: usize) -> Self; + + unsafe fn get_end(self) -> Self; + + fn add_bytes(self, offset: usize) -> Self; + + fn sub_bytes(self, offset: usize) -> Self; + + unsafe fn copy_bytes_to(self, dest: *mut U, count: usize); + + unsafe fn copy_val_to(self, dest: *mut U); + + unsafe fn read_to_box(self) -> Box; +} + +impl PtrExt for *const T { + type Pointee = T; + + fn addr(self) -> usize { + self.to_raw_parts().0 as usize + } + + fn align_up(self, align: usize) -> Self { + self.with_addr((self.addr() + align - 1) & !(align - 1)) + } + + fn with_addr_from(self, addr: *const U) -> Self { + self.with_addr(addr.addr()) + } + + fn with_addr(self, addr: usize) -> Self { + ptr::from_raw_parts(addr as _, self.to_raw_parts().1) + } + + unsafe fn get_end(self) -> Self { + self.add_bytes(size_of_val_raw(self)) + } + + fn add_bytes(self, offset: usize) -> Self { + self.with_addr_from(self.cast::().wrapping_add(offset)) + } + + fn sub_bytes(self, offset: usize) -> Self { + self.with_addr_from(self.cast::().wrapping_sub(offset)) + } + + unsafe fn copy_bytes_to(self, dest: *mut U, count: usize) { + self.cast::().copy_to(dest.cast(), count); + } + + unsafe fn copy_val_to(self, dest: *mut U) { + self.copy_bytes_to(dest, size_of_val_raw(self)); + } + + unsafe fn read_to_box(self) -> Box { + let alloc = alloc(Layout::for_value_raw(self)); + self.copy_val_to(alloc); + Box::from_raw(alloc.with_meta_from(self)) + } +} + +impl PtrExt for *mut T { + type Pointee = T; + + fn addr(self) -> usize { + self.to_raw_parts().0 as usize + } + + fn align_up(self, align: usize) -> Self { + self.with_addr((self.addr() + align - 1) & !(align - 1)) + } + + fn with_addr_from(self, addr: *const U) -> Self { + self.with_addr(addr.addr()) + } + + fn with_addr(self, addr: usize) -> Self { + ptr::from_raw_parts_mut(addr as _, self.to_raw_parts().1) + } + + unsafe fn get_end(self) -> Self { + self.add_bytes(size_of_val_raw(self)) + } + + fn add_bytes(self, offset: usize) -> Self { + self.with_addr_from(self.cast::().wrapping_add(offset)) + } + + fn sub_bytes(self, offset: usize) -> Self { + self.with_addr_from(self.cast::().wrapping_sub(offset)) + } + + unsafe fn copy_bytes_to(self, dest: *mut U, count: usize) { + self.cast::().copy_to(dest.cast(), count); + } + + unsafe fn copy_val_to(self, dest: *mut U) { + self.copy_bytes_to(dest, size_of_val_raw(self)); + } + + unsafe fn read_to_box(self) -> Box { + let alloc = alloc(Layout::for_value_raw(self)); + self.copy_val_to(alloc); + Box::from_raw(alloc.with_meta_from(self)) + } +} + +pub trait ConstPtrExt: Sealed { + fn data_ptr(self) -> *const (); + + fn with_meta(self, meta: ::Metadata) -> *const U; + + fn with_meta_from(self, ptr: *const U) -> *const U; +} + +impl ConstPtrExt for *const T { + fn data_ptr(self) -> *const () { + self.to_raw_parts().0 + } + + fn with_meta(self, meta: ::Metadata) -> *const U { + ptr::from_raw_parts(self.data_ptr(), meta) + } + + fn with_meta_from(self, ptr: *const U) -> *const U { + self.with_meta(ptr.to_raw_parts().1) + } +} + +pub trait MutPtrExt: Sealed { + fn data_ptr(self) -> *mut (); + + fn with_meta(self, meta: ::Metadata) -> *mut U; + + fn with_meta_from(self, ptr: *const U) -> *mut U; +} + +impl MutPtrExt for *mut T { + fn data_ptr(self) -> *mut () { + self.to_raw_parts().0 + } + + fn with_meta(self, meta: ::Metadata) -> *mut U { + ptr::from_raw_parts_mut(self.data_ptr(), meta) + } + + fn with_meta_from(self, ptr: *const U) -> *mut U { + self.with_meta(ptr.to_raw_parts().1) + } +} \ No newline at end of file