use ::core::mem::ManuallyDrop;
use crate::{prelude::*,
ptr,
Slot,
};
pub
mod slice;
#[repr(transparent)]
pub
struct StackBox<'frame, T : ?Sized + 'frame> {
unique_ptr: ptr::Unique<T>,
_covariant_lt: ::core::marker::PhantomData<&'frame ()>,
}
impl<'frame, T : 'frame> StackBox<'frame, T> {
#[inline(always)]
pub
fn new_in (slot: &'frame mut Slot<T>, value: T)
-> StackBox<'frame, T>
{
slot.stackbox(value)
}
#[inline]
pub
fn with_new<R, F> (value: T, ret: F) -> R
where
F: for<'local> FnOnce(StackBox<'local, T>) -> R,
{
ret(StackBox::new_in(&mut mk_slot(), value))
}
#[inline]
pub
fn into_inner (self: StackBox<'frame, T>)
-> T
{
unsafe {
let this = ManuallyDrop::new(self);
::core::ptr::read::<T>(&**this)
}
}
}
impl<'frame, T : ?Sized + 'frame> StackBox<'frame, T> {
#[inline]
pub
unsafe
fn assume_owns (it: &'frame mut ManuallyDrop<T>)
-> StackBox<'frame, T>
{
Self {
unique_ptr: ptr::Unique::<T>::from_raw(&mut **it),
_covariant_lt: Default::default(),
}
}
#[cfg(feature = "unsize")]
#[inline]
pub(in crate)
fn into_inner_unique(self)
-> ptr::Unique<T>
{
let this = ManuallyDrop::new(self);
unsafe {
::core::ptr::read(&this.unique_ptr)
}
}
}
impl<'frame, T : ?Sized + 'frame>
::core::ops::Deref
for
StackBox<'frame, T>
{
type Target = T;
#[inline]
fn deref (self: &'_ StackBox<'frame, T>)
-> &'_ T
{
&*self.unique_ptr
}
}
impl<'frame, T : ?Sized + 'frame>
::core::ops::DerefMut
for
StackBox<'frame, T>
{
#[inline]
fn deref_mut (self: &'_ mut StackBox<'frame, T>)
-> &'_ mut T
{
&mut *self.unique_ptr
}
}
impl<T : ?Sized> Drop for StackBox<'_, T> {
#[inline]
fn drop (self: &'_ mut Self)
{
unsafe {
ptr::Unique::<T>::drop_in_place(&mut self.unique_ptr)
}
}
}
#[cfg(feature = "unsize")]
unsafe impl<'frame, T : 'frame, U: ?Sized + 'frame>
::unsize::CoerciblePtr<U>
for
StackBox<'frame, T>
{
type Pointee = T;
type Output = StackBox<'frame, U>;
fn as_sized_ptr(self: &mut Self) -> *mut T {
&*self.unique_ptr as *const T as *mut T
}
unsafe fn replace_ptr(self, new: *mut U) -> StackBox<'frame, U> {
let _covariant_lt = self._covariant_lt;
let new_ptr = self
.into_inner_unique()
.into_raw_nonnull()
.as_mut()
.replace_ptr(new);
let unique_ptr = ptr::Unique::from_raw(new_ptr);
StackBox {
unique_ptr,
_covariant_lt,
}
}
}
#[macro_export]
macro_rules! stackbox {
(
// Same as `StackBox::new_in`, except for it allowing an unsized
// coercion to take place.
$place:expr,
$value:expr $(,)?
) => (match ($place, $value) { (place, value) => {
let ptr = $crate::Slot::__init_raw(place, value);
unsafe {
let _ = $crate::__::concat!(
"Safety: `", stringify!($place), "` has just been initialized",
);
$crate::StackBox::assume_owns(ptr)
}
}});
(
// Create a new `mut` `StackBox` without mentioning the backing _slot_:
// `let mut <binding> = stackbox!($expr);`
let mut $var:ident $(: $T:ty)? = $expr:expr
) => (
$crate::stackbox!($expr => let mut $var $(: $T)?)
);
(
// Create a new `StackBox` without mentioning the backing _slot_:
// `let <binding> = stackbox!($expr);`
let $var:ident $(: $T:ty)? = $expr:expr
) => (
$crate::stackbox!($expr => let $var $(: $T)?)
);
(
// Internal-ish: assign the result of a `stackbox!($expr)` to "some place"
$expr:expr => $($binding:tt)*
) => (
let ref mut ptr = $crate::__::ManuallyDrop::new($expr);
$($binding)* = unsafe { $crate::StackBox::assume_owns(ptr) };
);
(
let mut $var:ident
) => (
$crate::stackbox!(let mut $var = $var)
);
(
let $var:ident
) => (
$crate::stackbox!(let $var = $var)
);
(
$expr:expr
) => (
match &mut $crate::__::ManuallyDrop::new($expr) { ptr => {
#[allow(unused_unsafe)] {
unsafe {
$crate::StackBox::assume_owns(ptr)
}
}
}}
);
}