#![allow(dead_code)]
use core::marker::PhantomData;
use core::mem::MaybeUninit;
use crate::tracking::{self, ptr};
use crate::util::abort;
pub struct InvariantLifetime<'id>(PhantomData<*mut &'id ()>);
pub struct Unbranded;
pub trait Brand {}
impl<'id> Brand for InvariantLifetime<'id> {}
#[rustfmt::skip]
#[allow(clippy::missing_safety_doc)]
pub mod states {
pub struct Weak;
pub struct Uninit;
pub struct MaybeInit;
pub struct Init;
pub struct AlwaysInit;
pub unsafe trait State { type Borrowed; }
unsafe impl State for Weak { type Borrowed = Weak; }
unsafe impl State for Uninit { type Borrowed = Uninit; }
unsafe impl State for MaybeInit { type Borrowed = MaybeInit; }
unsafe impl State for Init { type Borrowed = AlwaysInit; } unsafe impl State for AlwaysInit { type Borrowed = AlwaysInit; }
pub unsafe trait RawAccess {}
unsafe impl RawAccess for Uninit {}
unsafe impl RawAccess for MaybeInit {}
unsafe impl RawAccess for Init {}
pub unsafe trait IsInit {}
unsafe impl IsInit for Init {}
unsafe impl IsInit for AlwaysInit {}
}
use states::*;
pub struct MutSlice<'l, B, T, S> {
begin: *mut T,
end: *mut T,
_lifetime: PhantomData<&'l mut T>,
_metadata: PhantomData<(B, S)>,
}
unsafe impl<'l, B, T, S> Send for MutSlice<'l, B, T, S> {}
impl<'l, B, T, S> core::fmt::Debug for MutSlice<'l, B, T, S> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("MutSlice")
.field("begin", &self.begin)
.field("end", &self.end)
.finish()
}
}
impl<'l, 'b, T> MutSlice<'l, InvariantLifetime<'b>, T, AlwaysInit> {
#[inline]
pub fn from_mut_slice<R>(
sl: &'l mut [T],
f: impl for<'b2> FnOnce(MutSlice<'l, InvariantLifetime<'b2>, T, AlwaysInit>) -> R,
) -> R {
let len = sl.len();
let ptr = sl.as_mut_ptr();
f(unsafe {
MutSlice::from_pair_unchecked(ptr, ptr.add(len))
})
}
}
impl<'l, 'b, T> MutSlice<'l, InvariantLifetime<'b>, T, MaybeInit> {
#[inline]
pub fn from_maybeuninit_mut_slice<R>(
sl: &'l mut [MaybeUninit<T>],
f: impl for<'b2> FnOnce(MutSlice<'l, InvariantLifetime<'b2>, T, MaybeInit>) -> R,
) -> R {
let len = sl.len();
let ptr = sl.as_mut_ptr() as *mut T;
f(unsafe {
MutSlice::from_pair_unchecked(ptr, ptr.add(len))
})
}
}
impl<'l, B, T, S> MutSlice<'l, B, T, S> {
#[inline]
pub unsafe fn from_pair_unchecked(begin: *mut T, end: *mut T) -> Self {
Self {
begin,
end,
_lifetime: PhantomData,
_metadata: PhantomData,
}
}
#[inline]
pub unsafe fn transmute_metadata<B2, S2>(self) -> MutSlice<'l, B2, T, S2> {
unsafe { MutSlice::from_pair_unchecked(self.begin, self.end) }
}
#[inline]
pub fn len(&self) -> usize {
unsafe { self.end.offset_from(self.begin) as usize }
}
#[inline]
pub fn contains(&self, ptr: *mut T) -> bool {
(self.begin..self.end).contains(&ptr)
}
#[inline]
pub fn split_at(self, i: usize) -> Option<(Self, Self)> {
unsafe {
if i <= self.len() {
let mid = self.begin.add(i);
Some((
Self::from_pair_unchecked(self.begin, mid),
Self::from_pair_unchecked(mid, self.end),
))
} else {
None
}
}
}
#[inline]
pub fn split_at_end(self, i: usize) -> Option<(Self, Self)> {
self.len().checked_sub(i).and_then(|ni| self.split_at(ni))
}
#[inline]
pub fn split_off_begin(&mut self, i: usize) -> Self {
if i <= self.len() {
unsafe {
let mid = self.begin.add(i);
let other = Self::from_pair_unchecked(self.begin, mid);
self.begin = mid;
other
}
} else {
abort()
}
}
#[inline]
pub fn split_off_end(&mut self, i: usize) -> Self {
if i <= self.len() {
unsafe {
let mid = self.end.sub(i);
let other = Self::from_pair_unchecked(mid, self.end);
self.end = mid;
other
}
} else {
abort()
}
}
pub fn begin_address(&self) -> usize {
self.begin as usize
}
pub fn end_address(&self) -> usize {
self.end as usize
}
}
impl<'l, B: Brand, T, S> MutSlice<'l, B, T, S> {
#[inline]
pub fn concat(self, right: Self) -> Self {
unsafe {
if self.end == right.begin {
Self::from_pair_unchecked(self.begin, right.end)
} else {
abort();
}
}
}
}
#[rustfmt::skip]
impl<'l, B, T, S> MutSlice<'l, B, T, S> {
#[inline] pub fn begin(&self) -> *mut T { self.begin }
#[inline] pub fn end(&self) -> *mut T { self.end }
}
#[rustfmt::skip]
impl<'l, B, T, S> MutSlice<'l, B, T, S> {
#[inline] pub unsafe fn add_begin(&mut self, n: usize) { self.begin = unsafe { self.begin.add(n) } }
#[inline] pub unsafe fn sub_begin(&mut self, n: usize) { self.begin = unsafe { self.begin.sub(n) } }
#[inline] pub unsafe fn wrapping_add_begin(&mut self, n: usize) { self.begin = self.begin.wrapping_add(n) }
#[inline] pub unsafe fn wrapping_sub_begin(&mut self, n: usize) { self.begin = self.begin.wrapping_sub(n) }
#[inline] pub unsafe fn add_end(&mut self, n: usize) { self.end = unsafe { self.end.add(n) } }
#[inline] pub unsafe fn sub_end(&mut self, n: usize) { self.end = unsafe { self.end.sub(n) } }
#[inline] pub unsafe fn wrapping_add_end(&mut self, n: usize) { self.end = self.end.wrapping_add(n) }
#[inline] pub unsafe fn wrapping_sub_end(&mut self, n: usize) { self.end = self.end.wrapping_sub(n) }
}
impl<'l, B, T> MutSlice<'l, B, T, Init> {
#[inline]
pub fn move_to<'dst_l, DstB>(
self,
dst: MutSlice<'dst_l, DstB, T, Uninit>,
) -> (MutSlice<'l, B, T, Uninit>, MutSlice<'dst_l, DstB, T, Init>) {
unsafe {
if self.len() != dst.len() {
abort();
}
ptr::copy_nonoverlapping(self.begin(), dst.begin(), self.len());
(self.assume_uninit(), dst.assume_init())
}
}
}
impl<'l, B, T> MutSlice<'l, B, T, AlwaysInit> {
#[inline]
pub unsafe fn raw(self) -> MutSlice<'l, B, T, Init> {
unsafe { self.transmute_metadata() }
}
}
impl<'l, B, T> MutSlice<'l, B, T, Init> {
#[inline]
pub fn always_init(self) -> MutSlice<'l, B, T, AlwaysInit> {
unsafe { self.transmute_metadata() }
}
}
impl<'l, B, T, S> MutSlice<'l, B, T, S> {
#[inline]
pub fn forget_brand(self) -> MutSlice<'l, Unbranded, T, S> {
unsafe { self.transmute_metadata() }
}
#[inline]
pub fn weak(&self) -> MutSlice<'l, B, T, Weak> {
unsafe { MutSlice::from_pair_unchecked(self.begin, self.end) }
}
}
impl<'l, B, T> MutSlice<'l, B, T, Weak> {
#[inline]
pub unsafe fn upgrade(self) -> MutSlice<'l, B, T, MaybeInit> {
unsafe { self.transmute_metadata() }
}
}
impl<'l, B, T, S: RawAccess> MutSlice<'l, B, T, S> {
#[inline]
pub unsafe fn assume_init(self) -> MutSlice<'l, B, T, Init> {
unsafe { self.transmute_metadata() }
}
#[inline]
pub fn assume_uninit(self) -> MutSlice<'l, B, T, Uninit> {
unsafe { self.transmute_metadata() }
}
#[inline]
pub fn allow_maybe_init(self) -> MutSlice<'l, B, T, MaybeInit> {
unsafe { self.transmute_metadata() }
}
}
impl<'l, B, T, S> MutSlice<'l, B, T, S> {
#[inline]
pub fn take(&mut self) -> Self {
unsafe {
let weak = self.weak();
self.sub_end(self.len());
weak.transmute_metadata()
}
}
}
impl<'l, B, T, S: IsInit> MutSlice<'l, B, T, S> {
#[inline]
pub fn as_slice<'a>(&'a self) -> &'a [T] {
unsafe { core::slice::from_raw_parts(self.begin, self.len()) }
}
#[inline]
pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
unsafe { core::slice::from_raw_parts_mut(self.begin, self.len()) }
}
}
impl<'l, B, T, S: State> MutSlice<'l, B, T, S> {
#[inline]
pub fn borrow<'a>(&'a mut self) -> MutSlice<'a, B, T, S::Borrowed> {
unsafe { MutSlice::from_pair_unchecked(self.begin, self.end) }
}
}
impl<'l, B, T> Clone for MutSlice<'l, B, T, Weak> {
#[inline]
fn clone(&self) -> Self {
self.weak()
}
}
#[inline(always)]
pub fn with_stack_scratch<const N: usize, T, R, F>(name: &'static str, f: F) -> R
where
F: for<'l, 'b> FnOnce(MutSlice<'l, InvariantLifetime<'b>, T, Uninit>) -> R,
{
let mut scratch_space: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
MutSlice::from_maybeuninit_mut_slice(&mut scratch_space, |scratch| {
tracking::register_buffer(name, scratch.weak());
let ret = f(scratch.assume_uninit());
tracking::deregister_buffer(name);
ret
})
}