use crate::{
extension_traits::{AsOut, MaybeUninitExt},
};
use ::core::{
mem::{self,
ManuallyDrop,
MaybeUninit,
},
ptr,
slice,
};
#[derive(Debug)]
#[repr(transparent)]
pub
struct Out<'out, T : 'out + ?Sized> (
ptr::NonNull<T>,
::core::marker::PhantomData<&'out mut T>,
);
unsafe impl<'out, T : ?Sized + 'out> Send for Out<'out, T>
where
&'out mut T : Send,
{}
unsafe impl<'out, T : ?Sized + 'out> Sync for Out<'out, T>
where
&'out mut T : Sync,
{}
impl<'out, T : 'out> From<&'out mut MaybeUninit<T>> for Out<'out, T> {
#[inline]
fn from (p: &'out mut MaybeUninit<T>)
-> Out<'out, T>
{
Out(
ptr::NonNull::<MaybeUninit<T>>::from(p).cast(),
Default::default(),
)
}
}
impl<'out, T : 'out> From<&'out mut T> for Out<'out, T>
where
T : Copy, {
#[inline]
fn from (p: &'out mut T)
-> Out<'out, T>
{
unsafe {
mem::transmute::<_, &'out mut MaybeUninit<T>>(p).into()
}
}
}
#[cfg(doc)]
use crate::extension_traits::ManuallyDropMut;
impl<'out, T : 'out> From<&'out mut ManuallyDrop<T>> for Out<'out, T> {
#[inline]
fn from (p: &'out mut ManuallyDrop<T>)
-> Out<'out, T>
{
unsafe {
mem::transmute::<_, &'out mut MaybeUninit<T>>(p).into()
}
}
}
impl<'out, T : 'out + ?Sized> Out<'out, T> {
#[inline]
pub
fn reborrow<'reborrow> (self: &'reborrow mut Out<'out, T>)
-> Out<'reborrow, T>
where
'out : 'reborrow,
{
Out(self.0, Default::default())
}
#[inline]
pub
fn r<'reborrow> (self: &'reborrow mut Out<'out, T>)
-> Out<'reborrow, T>
where
'out : 'reborrow,
{
self.reborrow()
}
}
impl<'out, T : 'out> Out<'out, T> {
#[inline]
pub
fn write (self: Out<'out, T>, value: T)
-> &'out mut T
{
unsafe {
self.0.as_ptr().write(value);
self.assume_init()
}
}
#[inline]
pub
fn replace (mut self: Out<'out, T>, value: T)
-> (MaybeUninit<T>, &'out mut T)
{
unsafe {
(
mem::replace(self.r().as_mut_uninit(), MaybeUninit::new(value)),
self.assume_init(),
)
}
}
#[inline]
pub
fn as_mut_ptr (self: &'_ mut Out<'out, T>)
-> *mut T
{
self.0.as_ptr()
}
#[inline]
pub
unsafe
fn assume_init (mut self: Out<'out, T>)
-> &'out mut T
{
&mut *self.as_mut_ptr()
}
#[inline]
pub
unsafe
fn as_mut_uninit (self: Out<'out, T>)
-> &'out mut MaybeUninit<T>
{
&mut *({self}.as_mut_ptr().cast())
}
}
impl<'out, T : 'out> Default for Out<'out, [T]> {
#[inline]
fn default ()
-> Self
{
<&mut [MaybeUninit<T>]>::into(&mut [])
}
}
impl<'out, T : 'out> From<&'out mut [T]> for Out<'out, [T]>
where
T : Copy,
{
#[inline]
fn from (slice: &'out mut [T])
-> Out<'out, [T]>
{
Out(
slice.into(),
Default::default(),
)
}
}
impl<'out, T : 'out> From<&'out mut [ManuallyDrop<T>]> for Out<'out, [T]> {
#[inline]
fn from (slice: &'out mut [ManuallyDrop<T>])
-> Out<'out, [T]>
{
unsafe {
Out(
ptr::NonNull::new_unchecked(
slice as *mut [ManuallyDrop<T>] as *mut [T]
),
Default::default(),
)
}
}
}
impl<'out, T : 'out> From<&'out mut [MaybeUninit<T>]> for Out<'out, [T]> {
#[inline]
fn from (slice: &'out mut [MaybeUninit<T>])
-> Out<'out, [T]>
{
unsafe {
Out(
ptr::NonNull::new_unchecked(
slice as *mut [MaybeUninit<T>] as *mut [T]
),
Default::default(),
)
}
}
}
impl<'out, T : 'out> Out<'out, [T]> {
#[inline]
pub
fn from_out (out: Out<'out, T>)
-> Out<'out, [T]>
{
unsafe {
slice::from_mut(out.as_mut_uninit())
.as_out()
}
}
#[inline]
pub
fn as_ptr (self: &'_ Self)
-> *const T
{
self.0.as_ptr().cast()
}
#[inline]
pub
fn as_mut_ptr (self: &'_ mut Self)
-> *mut T
{
self.0.as_ptr().cast()
}
#[inline]
pub
unsafe
fn as_mut_uninit (self: Out<'out, [T]>)
-> &'out mut [MaybeUninit<T>]
{
&mut *(self.0.as_ptr() as *mut [MaybeUninit<T>])
}
#[inline]
pub
fn get_out<Index> (self: Out<'out, [T]>, idx: Index)
-> Option<Index::Output>
where
Index : UsizeOrRange<'out, T>, {
macro_rules! impl_SliceIndex {(
$($Range:ty),+ $(,)?
) => (
$(
impl<'out, T : 'out> SliceIndex<'out, T> for $Range {
type Output = Out<'out, [T]>;
#[inline]
fn idx (self: Self, slice: Out<'out, [T]>)
-> Option<Out<'out, [T]>>
{
unsafe {
slice.as_mut_uninit()
.get_mut(self)
.map(Out::from)
}
}
}
)*
)}
impl<'out, T : 'out> SliceIndex<'out, T> for usize {
type Output = Out<'out, T>;
#[inline]
fn idx (self: usize, slice: Out<'out, [T]>)
-> Option<Out<'out, T>>
{
unsafe {
slice.as_mut_uninit()
.get_mut(self)
.map(Out::from)
}
}
}
impl_SliceIndex! {
::core::ops::Range<usize>,
::core::ops::RangeInclusive<usize>,
::core::ops::RangeFrom<usize>,
::core::ops::RangeTo<usize>,
::core::ops::RangeToInclusive<usize>,
::core::ops::RangeFull,
}
idx.idx(self)
}
#[inline]
pub
unsafe
fn get_unchecked_out<Index> (self: Out<'out, [T]>, idx: Index)
-> Index::Output
where
Index : UsizeOrRange<'out, T>, {
self.get_out(idx)
.unwrap_or_else(|| if cfg!(debug_assertions) {
panic!(concat!(
"Attempted to index out of bounds through unchecked ",
"indexing (this was detected thanks to a check still ",
"being present in debug mode).\n",
r"/!\ THIS IS A BUG AND A SOUNDNESS ISSUE /!\", "\n",
"Please submit an issue ASAP.",
));
} else {
::core::hint::unreachable_unchecked()
})
}
#[inline]
pub
fn as_uninit (self: Out<'out, [T]>)
-> &'out [MaybeUninit<T>]
{
unsafe {
&*(self.0.as_ptr() as *const [MaybeUninit<T>])
}
}
#[inline]
pub
unsafe
fn assume_all_init (mut self: Out<'out, [T]>) -> &'out mut [T]
{
let len = self.len();
slice::from_raw_parts_mut(
self.as_mut_ptr(),
len,
)
}
pub
fn copy_from_slice (
mut self: Out<'out, [T]>,
source_slice: &'_ [T],
) -> &'out mut [T]
where
T : Copy,
{
unsafe {
self.r()
.as_mut_uninit()
.copy_from_slice(
<[MaybeUninit<T>]>::from_ref(source_slice)
)
;
self.assume_all_init()
}
}
#[inline]
pub
fn init_with (
mut self: Out<'out, [T]>,
iterable: impl IntoIterator<Item = T>,
) -> &'out mut [T]
{
let len = self.len();
let mut iter_out = self.iter_out();
iter_out
.by_ref()
.zip(iterable)
.for_each(|(at_dst, next)| { at_dst.write(next); })
;
let init_count = len - iter_out.remaining().len();
unsafe {
self.get_unchecked_out(.. init_count)
.assume_all_init()
}
}
#[inline]
pub
fn iter_out<'reborrow> (self: &'reborrow mut Out<'out, [T]>)
-> iter::IterOut<'reborrow, T>
{
self.into_iter()
}
#[inline]
pub
fn split_at_out (self: Out<'out, [T]>, idx: usize)
-> (Out<'out, [T]>, Out<'out, [T]> )
{
let (left, right) = unsafe { self.as_mut_uninit() }.split_at_mut(idx);
(left.as_out(), right.as_out())
}
}
impl<'out, T : 'out> ::core::ops::Deref for Out<'out, [T]> {
type Target = [MaybeUninit<T>];
#[inline]
fn deref (self: &'_ Self)
-> &'_ [MaybeUninit<T>]
{
unsafe {
&*(self.0.as_ptr() as *const [MaybeUninit<T>])
}
}
}
use private::{SliceIndex, SliceIndex as UsizeOrRange};
mod private {
use super::*;
pub
trait SliceIndex<'out, T> {
type Output : 'out;
fn idx (self: Self, slice: Out<'out, [T]>)
-> Option<Self::Output>
;
}
}
pub
mod iter {
use super::*;
#[allow(missing_debug_implementations)]
pub
struct IterOut<'out, T : 'out> {
slice: Out<'out, [T]>,
}
impl<'out, T : 'out> IterOut<'out, T> {
#[inline]
pub
fn remaining (self: IterOut<'out, T>)
-> Out<'out, [T]>
{
self.slice
}
}
impl<'out, T : 'out> IntoIterator for Out<'out, [T]> {
type Item = Out<'out, T>;
type IntoIter = IterOut<'out, T>;
fn into_iter (self: Out<'out, [T]>)
-> IterOut<'out, T>
{
IterOut { slice: self }
}
}
impl<'out, 'inner : 'out, T : 'inner> IntoIterator
for &'out mut Out<'inner, [T]>
{
type Item = Out<'out, T>;
type IntoIter = IterOut<'out, T>;
#[inline]
fn into_iter (self: &'out mut Out<'inner, [T]>)
-> IterOut<'out, T>
{
self.reborrow().into_iter()
}
}
impl<'out, T : 'out> Iterator for IterOut<'out, T> {
type Item = Out<'out, T>;
#[inline]
fn next (self: &'_ mut IterOut<'out, T>)
-> Option<Out<'out, T>>
{
if self.slice.is_empty() { return None; }
let slice = mem::replace(&mut self.slice, Out::default());
let (first, rest) = slice.split_at_out(1);
self.slice = rest;
Some(unsafe {
first.get_unchecked_out(0)
})
}
}
}