use core::{
ops::{Deref, DerefMut},
slice::SliceIndex,
};
use munge::{Borrow, Destructure, Restructure};
use crate::traits::NoUndef;
pub struct Seal<'a, T: ?Sized> {
inner: &'a mut T,
}
impl<'a, T: ?Sized> Seal<'a, T> {
pub fn new(inner: &'a mut T) -> Self {
Self { inner }
}
pub fn unseal(self) -> &'a mut T
where
T: NoUndef + Unpin,
{
self.inner
}
pub fn unseal_ref(self) -> &'a T {
self.inner
}
pub unsafe fn unseal_unchecked(self) -> &'a mut T {
self.inner
}
pub fn as_mut(&mut self) -> Seal<'_, T> {
Seal::new(self.inner)
}
}
impl<T: ?Sized> AsRef<T> for Seal<'_, T> {
fn as_ref(&self) -> &T {
self.inner
}
}
impl<T: ?Sized> Deref for Seal<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl<T: NoUndef + Unpin + ?Sized> DerefMut for Seal<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut().unseal()
}
}
unsafe impl<T: ?Sized> Destructure for Seal<'_, T> {
type Underlying = T;
type Destructuring = Borrow;
fn underlying(&mut self) -> *mut Self::Underlying {
self.inner
}
}
unsafe impl<'a, T: ?Sized, U: 'a + ?Sized> Restructure<U> for Seal<'a, T> {
type Restructured = Seal<'a, U>;
unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured {
Seal::new(unsafe { &mut *ptr })
}
}
impl<'a, T> Seal<'a, [T]> {
pub fn index<I: SliceIndex<[T]>>(
self,
index: I,
) -> Seal<'a, <I as SliceIndex<[T]>>::Output> {
let ptr = unsafe { Seal::unseal_unchecked(self) };
Seal::new(&mut ptr[index])
}
}