180 lines
4.7 KiB
Rust
180 lines
4.7 KiB
Rust
use std::{alloc::{alloc, Layout}, mem::size_of_val, ptr::addr_of_mut};
|
|
|
|
use self::__priv::Sealed;
|
|
|
|
mod __priv {
|
|
pub trait Sealed {}
|
|
|
|
impl<T: ?Sized> Sealed for *const T {}
|
|
impl<T: ?Sized> 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<U: ?Sized>(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<U: ?Sized>(self, dest: *mut U, count: usize);
|
|
|
|
unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U);
|
|
|
|
unsafe fn read_to_box(self) -> Box<Self::Pointee>;
|
|
}
|
|
|
|
impl<T: ?Sized> PtrExt for *const T {
|
|
type Pointee = T;
|
|
|
|
fn addr(self) -> usize {
|
|
self.data_ptr() as usize
|
|
}
|
|
|
|
fn align_up(self, align: usize) -> Self {
|
|
self.with_addr((self.addr() + align - 1) & !(align - 1))
|
|
}
|
|
|
|
fn with_addr_from<U: ?Sized>(self, addr: *const U) -> Self {
|
|
self.with_addr(addr.addr())
|
|
}
|
|
|
|
fn with_addr(mut self, addr: usize) -> Self {
|
|
// TODO: aaaaand this is cheating. sorry yall, cant do this until `set_ptr_value` lands
|
|
unsafe { *addr_of_mut!(self).cast() = addr }
|
|
self
|
|
}
|
|
|
|
unsafe fn get_end(self) -> Self {
|
|
// TODO: _raw
|
|
self.add_bytes(size_of_val(&*self))
|
|
}
|
|
|
|
fn add_bytes(self, offset: usize) -> Self {
|
|
self.with_addr_from(self.cast::<u8>().wrapping_add(offset))
|
|
}
|
|
|
|
fn sub_bytes(self, offset: usize) -> Self {
|
|
self.with_addr_from(self.cast::<u8>().wrapping_sub(offset))
|
|
}
|
|
|
|
unsafe fn copy_bytes_to<U: ?Sized>(self, dest: *mut U, count: usize) {
|
|
self.cast::<u8>().copy_to(dest.cast(), count);
|
|
}
|
|
|
|
unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U) {
|
|
// TODO: _raw
|
|
self.copy_bytes_to(dest, size_of_val(&*self));
|
|
}
|
|
|
|
unsafe fn read_to_box(self) -> Box<Self::Pointee> {
|
|
// TODO: _raw
|
|
let alloc = alloc(Layout::for_value(&*self));
|
|
self.copy_val_to(alloc);
|
|
Box::from_raw(alloc.with_meta_from(self))
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized> PtrExt for *mut T {
|
|
type Pointee = T;
|
|
|
|
fn addr(self) -> usize {
|
|
self.data_ptr() as usize
|
|
}
|
|
|
|
fn align_up(self, align: usize) -> Self {
|
|
self.with_addr((self.addr() + align - 1) & !(align - 1))
|
|
}
|
|
|
|
fn with_addr_from<U: ?Sized>(self, addr: *const U) -> Self {
|
|
self.with_addr(addr.addr())
|
|
}
|
|
|
|
fn with_addr(mut self, addr: usize) -> Self {
|
|
// TODO: aaaaand this is cheating. sorry yall, cant do this until `set_ptr_value` lands
|
|
unsafe { *addr_of_mut!(self).cast() = addr }
|
|
self
|
|
}
|
|
|
|
unsafe fn get_end(self) -> Self {
|
|
// TODO: _raw
|
|
self.add_bytes(size_of_val(&*self))
|
|
}
|
|
|
|
fn add_bytes(self, offset: usize) -> Self {
|
|
self.with_addr_from(self.cast::<u8>().wrapping_add(offset))
|
|
}
|
|
|
|
fn sub_bytes(self, offset: usize) -> Self {
|
|
self.with_addr_from(self.cast::<u8>().wrapping_sub(offset))
|
|
}
|
|
|
|
unsafe fn copy_bytes_to<U: ?Sized>(self, dest: *mut U, count: usize) {
|
|
self.cast::<u8>().copy_to(dest.cast(), count);
|
|
}
|
|
|
|
unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U) {
|
|
// TODO: _raw
|
|
self.copy_bytes_to(dest, size_of_val(&*self));
|
|
}
|
|
|
|
unsafe fn read_to_box(self) -> Box<Self::Pointee> {
|
|
// TODO: _raw
|
|
let alloc = alloc(Layout::for_value(&*self));
|
|
self.copy_val_to(alloc);
|
|
Box::from_raw(alloc.with_meta_from(self))
|
|
}
|
|
}
|
|
|
|
#[allow(clippy::module_name_repetitions)]
|
|
pub trait ConstPtrExt: Sealed {
|
|
fn data_ptr(self) -> *const ();
|
|
|
|
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *const U;
|
|
}
|
|
|
|
impl<T: ?Sized> ConstPtrExt for *const T {
|
|
fn data_ptr(self) -> *const () {
|
|
self.cast()
|
|
}
|
|
|
|
// fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *const U {
|
|
// ptr::from_raw_parts(self.data_ptr(), meta)
|
|
// }
|
|
|
|
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *const U {
|
|
ptr.with_addr_from(self)
|
|
}
|
|
}
|
|
|
|
#[allow(clippy::module_name_repetitions)]
|
|
pub trait MutPtrExt: Sealed {
|
|
fn data_ptr(self) -> *mut ();
|
|
|
|
// fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *mut U;
|
|
|
|
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *mut U;
|
|
}
|
|
|
|
impl<T: ?Sized> MutPtrExt for *mut T {
|
|
fn data_ptr(self) -> *mut () {
|
|
self.cast()
|
|
}
|
|
|
|
// fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *mut U {
|
|
// ptr::from_raw_parts_mut(self.data_ptr(), meta)
|
|
// }
|
|
|
|
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *mut U {
|
|
ptr.with_addr_from(self) as _
|
|
}
|
|
} |