use std::{marker::PhantomData, ptr::NonNull};
pub use sealed::{AsMutPtr, AsPtr, Precursor};
#[derive(Debug, Clone, Copy)]
pub struct SlicePtr<'a, T> {
ptr: NonNull<T>,
lifetime: PhantomData<&'a T>,
}
impl<T> SlicePtr<'_, T> {
pub(crate) unsafe fn new_unchecked(ptr: NonNull<T>) -> Self {
Self {
ptr,
lifetime: PhantomData,
}
}
}
unsafe impl<T: Sync> Send for SlicePtr<'_, T> {}
unsafe impl<T: Sync> Sync for SlicePtr<'_, T> {}
#[derive(Debug)]
pub struct MutSlicePtr<'a, T> {
ptr: NonNull<T>,
lifetime: PhantomData<&'a mut T>,
}
impl<T> MutSlicePtr<'_, T> {
pub(crate) unsafe fn new_unchecked(ptr: NonNull<T>) -> Self {
Self {
ptr,
lifetime: PhantomData,
}
}
}
unsafe impl<T: Send> Send for MutSlicePtr<'_, T> {}
unsafe impl<T: Sync> Sync for MutSlicePtr<'_, T> {}
mod sealed {
use std::{marker::PhantomData, ptr::NonNull};
use super::{MutSlicePtr, SlicePtr};
use crate::alloc::{AllocatorCore, Poly};
pub unsafe trait Precursor<Target>
where
Target: AsPtr,
{
fn precursor_into(self) -> Target;
fn precursor_len(&self) -> usize;
}
unsafe impl<'a, T> Precursor<SlicePtr<'a, T>> for &'a [T] {
fn precursor_into(self) -> SlicePtr<'a, T> {
SlicePtr {
ptr: unsafe { NonNull::new_unchecked(self.as_ptr().cast_mut()) },
lifetime: PhantomData,
}
}
fn precursor_len(&self) -> usize {
<[T]>::len(self)
}
}
unsafe impl<'a, T> Precursor<SlicePtr<'a, T>> for &'a mut [T] {
fn precursor_into(self) -> SlicePtr<'a, T> {
SlicePtr {
ptr: unsafe { NonNull::new_unchecked(self.as_ptr().cast_mut()) },
lifetime: PhantomData,
}
}
fn precursor_len(&self) -> usize {
self.len()
}
}
unsafe impl<'a, T> Precursor<MutSlicePtr<'a, T>> for &'a mut [T] {
fn precursor_into(self) -> MutSlicePtr<'a, T> {
MutSlicePtr {
ptr: unsafe { NonNull::new_unchecked(self.as_mut_ptr()) },
lifetime: PhantomData,
}
}
fn precursor_len(&self) -> usize {
self.len()
}
}
unsafe impl<T, A> Precursor<Poly<[T], A>> for Poly<[T], A>
where
A: AllocatorCore,
{
fn precursor_into(self) -> Poly<[T], A> {
self
}
fn precursor_len(&self) -> usize {
self.len()
}
}
pub unsafe trait AsPtr {
type Type;
fn as_ptr(&self) -> *const Self::Type;
}
pub unsafe trait AsMutPtr: AsPtr {
fn as_mut_ptr(&mut self) -> *mut Self::Type;
}
unsafe impl<T> AsPtr for SlicePtr<'_, T> {
type Type = T;
fn as_ptr(&self) -> *const T {
self.ptr.as_ptr().cast_const()
}
}
unsafe impl<T> AsPtr for MutSlicePtr<'_, T> {
type Type = T;
fn as_ptr(&self) -> *const T {
self.ptr.as_ptr().cast_const()
}
}
unsafe impl<T> AsMutPtr for MutSlicePtr<'_, T> {
fn as_mut_ptr(&mut self) -> *mut T {
self.ptr.as_ptr()
}
}
unsafe impl<T, A> AsPtr for Poly<[T], A>
where
A: AllocatorCore,
{
type Type = T;
fn as_ptr(&self) -> *const T {
<[T]>::as_ptr(self)
}
}
unsafe impl<T, A> AsMutPtr for Poly<[T], A>
where
A: AllocatorCore,
{
fn as_mut_ptr(&mut self) -> *mut T {
<[T]>::as_mut_ptr(&mut *self)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::alloc::{GlobalAllocator, Poly};
fn slice_ptr_from_const_slice(base: &[u8]) {
let ptr = base.as_ptr();
assert!(!ptr.is_null(), "slices must not return null pointers");
let slice_ptr: SlicePtr<'_, u8> = base.precursor_into();
assert_eq!(slice_ptr.as_ptr(), ptr);
assert_eq!(base.precursor_len(), base.len());
let derived = unsafe {
std::slice::from_raw_parts(base.precursor_into().as_ptr(), base.precursor_len())
};
assert_eq!(derived.as_ptr(), ptr);
assert_eq!(derived.len(), base.len());
}
#[test]
fn test_slice_ptr_from_const_slice() {
slice_ptr_from_const_slice(&[]);
slice_ptr_from_const_slice(&[1]);
slice_ptr_from_const_slice(&[1, 2]);
for len in 0..10 {
let base: Vec<u8> = vec![0; len];
slice_ptr_from_const_slice(&base);
}
}
fn slice_ptr_from_mut_slice(base: &mut [u8]) {
let ptr = base.as_ptr();
let len = base.len();
assert!(!ptr.is_null(), "slices must not return null pointers");
let precursor_len = <&mut [u8] as Precursor<SlicePtr<'_, u8>>>::precursor_len(&base);
assert_eq!(precursor_len, base.len());
let slice_ptr: SlicePtr<'_, u8> = base.precursor_into();
assert_eq!(slice_ptr.as_ptr(), ptr);
let derived = unsafe { std::slice::from_raw_parts(slice_ptr.as_ptr(), precursor_len) };
assert_eq!(derived.as_ptr(), ptr);
assert_eq!(derived.len(), len);
}
#[test]
fn test_slice_ptr_from_mut_slice() {
slice_ptr_from_mut_slice(&mut []);
slice_ptr_from_mut_slice(&mut [1]);
slice_ptr_from_mut_slice(&mut [1, 2]);
for len in 0..10 {
let mut base: Vec<u8> = vec![0; len];
slice_ptr_from_mut_slice(&mut base);
}
}
fn mut_slice_ptr_from_mut_slice(base: &mut [u8]) {
let ptr = base.as_mut_ptr();
let len = base.len();
assert!(!ptr.is_null(), "slices must not return null pointers");
let precursor_len = <&mut [u8] as Precursor<SlicePtr<'_, u8>>>::precursor_len(&base);
assert_eq!(precursor_len, base.len());
let mut slice_ptr: MutSlicePtr<'_, u8> = base.precursor_into();
assert_eq!(slice_ptr.as_ptr(), ptr.cast_const());
assert_eq!(slice_ptr.as_mut_ptr(), ptr);
let derived =
unsafe { std::slice::from_raw_parts_mut(slice_ptr.as_mut_ptr(), precursor_len) };
assert_eq!(derived.as_ptr(), ptr);
assert_eq!(derived.len(), len);
}
#[test]
fn test_mut_slice_ptr_from_mut_slice() {
mut_slice_ptr_from_mut_slice(&mut []);
mut_slice_ptr_from_mut_slice(&mut [1]);
mut_slice_ptr_from_mut_slice(&mut [1, 2]);
for len in 0..10 {
let mut base: Vec<u8> = vec![0; len];
mut_slice_ptr_from_mut_slice(&mut base);
}
}
fn box_from_box(base: Poly<[u8], GlobalAllocator>) {
let ptr = base.as_ptr();
let len = base.len();
assert!(!ptr.is_null(), "slices must not return null pointers");
assert_eq!(base.precursor_len(), len);
let mut derived = base.precursor_into();
assert_eq!(derived.as_ptr(), ptr);
assert_eq!(derived.as_mut_ptr(), ptr.cast_mut());
assert_eq!(derived.len(), len);
}
#[test]
fn test_box() {
box_from_box(Poly::from_iter([].into_iter(), GlobalAllocator).unwrap());
box_from_box(Poly::from_iter([1].into_iter(), GlobalAllocator).unwrap());
box_from_box(Poly::from_iter([1, 2].into_iter(), GlobalAllocator).unwrap());
for len in 0..10 {
let base = Poly::broadcast(0, len, GlobalAllocator).unwrap();
box_from_box(base);
}
}
}