dyn_vec/src/ptr_ext.rs
2022-12-26 11:39:50 -06:00

215 lines
5.3 KiB
Rust

use std::{
alloc::{alloc, Layout},
mem::size_of_val,
};
#[cfg(not(feature = "unstable"))]
use std::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(self, addr: usize) -> Self {
#[cfg(feature = "unstable")]
{
self.wrapping_byte_sub(self.addr()).wrapping_byte_add(addr)
}
#[cfg(not(feature = "unstable"))]
{
let mut this = self;
unsafe { *addr_of_mut!(this).cast() = addr }
this
}
}
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(self, addr: usize) -> Self {
#[cfg(feature = "unstable")]
{
self.wrapping_byte_sub(self.addr()).wrapping_byte_add(addr)
}
#[cfg(not(feature = "unstable"))]
{
let mut this = self;
unsafe { *addr_of_mut!(this).cast() = addr }
this
}
}
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 {
#[cfg(feature = "unstable")]
{
self.with_metadata_of(ptr)
}
#[cfg(not(feature = "unstable"))]
{
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 {
#[cfg(feature = "unstable")]
{
self.with_metadata_of(ptr as _)
}
#[cfg(not(feature = "unstable"))]
{
ptr.with_addr_from(self) as _
}
}
}