#![no_std]
use core::{
cmp::Ordering,
fmt::{self, Debug, Display},
hash::{Hash, Hasher},
marker::PhantomData,
ops::{Deref, DerefMut, Range, RangeFrom, RangeFull, RangeTo},
pin::{pin, Pin},
ptr::NonNull,
slice,
str::Chars,
};
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
#[cfg(feature = "derive")]
pub use temp_inst_derive::{TempRepr, TempReprMut, TempReprMutChk};
use mapped::*;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TempInst<'a, T: TempRepr + 'a>(T, PhantomData<T::Shared<'a>>);
impl<'a, T: TempRepr> TempInst<'a, T> {
#[must_use]
pub fn new(obj: T::Shared<'a>) -> Self {
unsafe { TempInst(T::new_temp(obj), PhantomData) }
}
pub fn call_with<R>(obj: T::Shared<'a>, f: impl FnOnce(&T) -> R) -> R {
let inst = Self::new(obj);
f(&inst)
}
}
impl<T: TempRepr> Deref for TempInst<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<'a, T: TempRepr<Shared<'a>: Default>> Default for TempInst<'a, T> {
fn default() -> Self {
TempInst::new(Default::default())
}
}
impl<T: TempRepr + Debug> Debug for TempInst<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<T: TempRepr + Display> Display for TempInst<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TempInstPin<'a, T: TempReprMut + 'a>(T, PhantomData<T::Mutable<'a>>);
impl<'a, T: TempReprMut> TempInstPin<'a, T> {
#[must_use]
pub fn new(obj: T::Mutable<'a>) -> Self {
unsafe { TempInstPin(T::new_temp_mut(obj), PhantomData) }
}
#[must_use]
pub fn deref_pin(self: Pin<&mut Self>) -> Pin<&mut T> {
unsafe { self.map_unchecked_mut(|inst| &mut inst.0) }
}
pub fn call_with<R>(obj: T::Mutable<'a>, f: impl FnOnce(Pin<&mut T>) -> R) -> R {
let inst = pin!(Self::new(obj));
f(inst.deref_pin())
}
}
impl<T: TempReprMut> Deref for TempInstPin<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<'a, T: TempReprMut<Mutable<'a>: Default>> Default for TempInstPin<'a, T> {
fn default() -> Self {
TempInstPin::new(Default::default())
}
}
impl<T: TempReprMut + Debug> Debug for TempInstPin<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<T: TempReprMut + Display> Display for TempInstPin<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TempInstMut<'a, T: TempReprMutChk + 'a>(T, T::SwapChkData, PhantomData<T::Mutable<'a>>);
impl<'a, T: TempReprMutChk> TempInstMut<'a, T> {
#[must_use]
pub unsafe fn new(obj: T::Mutable<'a>) -> Self {
let temp = T::new_temp_mut(obj);
let chk_data = temp.swap_chk_data();
TempInstMut(temp, chk_data, PhantomData)
}
pub fn call_with<R>(obj: T::Mutable<'a>, f: impl FnOnce(&mut T) -> R) -> R {
let mut inst = unsafe { Self::new(obj) };
f(&mut inst)
}
}
impl<T: TempReprMutChk> Deref for TempInstMut<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: TempReprMutChk> DerefMut for TempInstMut<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T: TempReprMutChk<Mutable<'static>: Default>> Default for TempInstMut<'static, T> {
fn default() -> Self {
unsafe { TempInstMut::new(Default::default()) }
}
}
impl<T: TempReprMutChk + Debug> Debug for TempInstMut<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<T: TempReprMutChk + Display> Display for TempInstMut<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<T: TempReprMutChk> Drop for TempInstMut<'_, T> {
fn drop(&mut self) {
if self.0.swap_chk_data() != self.1 {
modification_panic();
}
}
}
#[cfg(feature = "std")]
fn modification_panic_fn() {
let orig_hook = std::panic::take_hook();
std::panic::set_hook(std::boxed::Box::new(move |panic_info| {
orig_hook(panic_info);
std::process::abort()
}));
panic!("TempInstMut instance was modified; this is not allowed because it violates safety guarantees");
}
#[cfg(not(feature = "std"))]
fn modification_panic_fn() {
loop {}
}
static mut MODIFICATION_PANIC_FN: fn() = modification_panic_fn;
pub unsafe fn set_modification_panic_fn(panic_fn: fn()) {
MODIFICATION_PANIC_FN = panic_fn;
}
fn modification_panic() {
unsafe { MODIFICATION_PANIC_FN() }
}
pub unsafe trait TempRepr {
type Shared<'a>
where
Self: 'a;
unsafe fn new_temp(obj: Self::Shared<'_>) -> Self;
fn get(&self) -> Self::Shared<'_>;
}
pub unsafe trait TempReprMut: TempRepr {
type Mutable<'a>
where
Self: 'a;
unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self;
fn get_mut(&mut self) -> Self::Mutable<'_>;
fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_>;
}
pub unsafe trait TempReprMutChk: TempReprMut {
type SwapChkData: PartialEq;
fn swap_chk_data(&self) -> Self::SwapChkData;
}
pub trait AlwaysShared: TempRepr {}
unsafe impl<T: AlwaysShared> TempReprMut for T {
type Mutable<'a> = Self::Shared<'a> where Self: 'a;
unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
Self::new_temp(obj)
}
fn get_mut(&mut self) -> Self::Mutable<'_> {
self.get()
}
fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
self.into_ref().get_ref().get()
}
}
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct SelfRepr<T: Clone>(T);
unsafe impl<T: Clone> TempRepr for SelfRepr<T> {
type Shared<'a> = T where Self: 'a;
unsafe fn new_temp(obj: T) -> Self {
SelfRepr(obj)
}
fn get(&self) -> T {
self.0.clone()
}
}
impl<T: Clone> AlwaysShared for SelfRepr<T> {}
unsafe impl<T: Clone> TempReprMutChk for SelfRepr<T> {
type SwapChkData = ();
fn swap_chk_data(&self) -> Self::SwapChkData {}
}
pub struct TempRef<T: ?Sized>(NonNull<T>);
unsafe impl<T: ?Sized> TempRepr for TempRef<T> {
type Shared<'a> = &'a T where Self: 'a;
unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
TempRef(obj.into())
}
fn get(&self) -> Self::Shared<'_> {
unsafe { self.0.as_ref() }
}
}
impl<T: ?Sized> AlwaysShared for TempRef<T> {}
unsafe impl<T: ?Sized> TempReprMutChk for TempRef<T> {
type SwapChkData = NonNull<T>;
fn swap_chk_data(&self) -> Self::SwapChkData {
self.0
}
}
impl<T: ?Sized> Deref for TempRef<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.get()
}
}
impl<T: ?Sized + PartialEq> PartialEq for TempRef<T> {
fn eq(&self, other: &Self) -> bool {
self.get() == other.get()
}
}
impl<T: ?Sized + Eq> Eq for TempRef<T> {}
impl<T: ?Sized + PartialOrd> PartialOrd for TempRef<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.get().partial_cmp(other.get())
}
fn lt(&self, other: &Self) -> bool {
self.get() < other.get()
}
fn le(&self, other: &Self) -> bool {
self.get() <= other.get()
}
fn gt(&self, other: &Self) -> bool {
self.get() > other.get()
}
fn ge(&self, other: &Self) -> bool {
self.get() >= other.get()
}
}
impl<T: ?Sized + Ord> Ord for TempRef<T> {
fn cmp(&self, other: &Self) -> Ordering {
self.get().cmp(other.get())
}
}
impl<T: ?Sized + Hash> Hash for TempRef<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.get().hash(state);
}
}
impl<T: ?Sized + Debug> Debug for TempRef<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.get().fmt(f)
}
}
impl<T: ?Sized + Display> Display for TempRef<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.get().fmt(f)
}
}
unsafe impl<T: ?Sized + Sync> Send for TempRef<T> {}
unsafe impl<T: ?Sized + Sync> Sync for TempRef<T> {}
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TempRefMut<T: ?Sized>(TempRef<T>, PhantomData<*mut T>);
unsafe impl<T: ?Sized> TempRepr for TempRefMut<T> {
type Shared<'a> = &'a T where Self: 'a;
unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
TempRefMut(TempRef::new_temp(obj), PhantomData)
}
fn get(&self) -> Self::Shared<'_> {
self.0.get()
}
}
unsafe impl<T: ?Sized> TempReprMut for TempRefMut<T> {
type Mutable<'a> = &'a mut T where Self: 'a;
unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
TempRefMut(TempRef(obj.into()), PhantomData)
}
fn get_mut(&mut self) -> Self::Mutable<'_> {
unsafe { self.0 .0.as_mut() }
}
fn get_mut_pinned(mut self: Pin<&mut Self>) -> Self::Mutable<'_> {
unsafe { self.0 .0.as_mut() }
}
}
unsafe impl<T: ?Sized> TempReprMutChk for TempRefMut<T> {
type SwapChkData = NonNull<T>;
fn swap_chk_data(&self) -> Self::SwapChkData {
self.0.swap_chk_data()
}
}
impl<T: ?Sized> Deref for TempRefMut<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.get()
}
}
impl<T: ?Sized> DerefMut for TempRefMut<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.get_mut()
}
}
impl<T: ?Sized + Debug> Debug for TempRefMut<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.get().fmt(f)
}
}
impl<T: ?Sized + Display> Display for TempRefMut<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.get().fmt(f)
}
}
unsafe impl<T: ?Sized + Send> Send for TempRefMut<T> {}
unsafe impl<T: ?Sized + Sync> Sync for TempRefMut<T> {}
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TempRefPin<T: ?Sized>(TempRefMut<T>);
unsafe impl<T: ?Sized> TempRepr for TempRefPin<T> {
type Shared<'a> = &'a T where Self: 'a;
unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
TempRefPin(TempRefMut::new_temp(obj))
}
fn get(&self) -> Self::Shared<'_> {
self.0.get()
}
}
unsafe impl<T: ?Sized> TempReprMut for TempRefPin<T> {
type Mutable<'a> = Pin<&'a mut T> where Self: 'a;
unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
TempRefPin(TempRefMut::new_temp_mut(obj.get_unchecked_mut()))
}
fn get_mut(&mut self) -> Self::Mutable<'_> {
unsafe { Pin::new_unchecked(self.0.get_mut()) }
}
fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
unsafe { Pin::new_unchecked(self.map_unchecked_mut(|temp| &mut temp.0).get_mut_pinned()) }
}
}
unsafe impl<T: ?Sized> TempReprMutChk for TempRefPin<T> {
type SwapChkData = NonNull<T>;
fn swap_chk_data(&self) -> Self::SwapChkData {
self.0.swap_chk_data()
}
}
impl<T: ?Sized> Deref for TempRefPin<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.get()
}
}
impl<T: ?Sized + Debug> Debug for TempRefPin<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.get().fmt(f)
}
}
impl<T: ?Sized + Display> Display for TempRefPin<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.get().fmt(f)
}
}
#[cfg(feature = "alloc")]
pub enum TempCow<T: ?Sized + alloc::borrow::ToOwned> {
Borrowed(TempRef<T>),
Owned(T::Owned),
}
#[cfg(feature = "alloc")]
unsafe impl<T: ?Sized + alloc::borrow::ToOwned<Owned: Clone>> TempRepr for TempCow<T> {
type Shared<'a> = alloc::borrow::Cow<'a, T> where Self: 'a;
unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
match obj {
alloc::borrow::Cow::Borrowed(obj) => TempCow::Borrowed(TempRef::new_temp(obj)),
alloc::borrow::Cow::Owned(obj) => TempCow::Owned(obj),
}
}
fn get(&self) -> Self::Shared<'_> {
match self {
TempCow::Borrowed(temp) => alloc::borrow::Cow::Borrowed(temp.get()),
TempCow::Owned(temp) => alloc::borrow::Cow::Owned(temp.clone()),
}
}
}
#[cfg(feature = "alloc")]
impl<T: ?Sized + alloc::borrow::ToOwned<Owned: Clone>> AlwaysShared for TempCow<T> {}
#[cfg(feature = "alloc")]
unsafe impl<T: ?Sized + alloc::borrow::ToOwned<Owned: Clone>> TempReprMutChk for TempCow<T> {
type SwapChkData = Option<NonNull<T>>;
fn swap_chk_data(&self) -> Self::SwapChkData {
match self {
TempCow::Borrowed(temp) => Some(temp.swap_chk_data()),
TempCow::Owned(_) => None,
}
}
}
unsafe impl<T: TempRepr> TempRepr for Option<T> {
type Shared<'a> = Option<T::Shared<'a>> where Self: 'a;
unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
Some(T::new_temp(obj?))
}
fn get(&self) -> Self::Shared<'_> {
Some(self.as_ref()?.get())
}
}
unsafe impl<T: TempReprMut> TempReprMut for Option<T> {
type Mutable<'a> = Option<T::Mutable<'a>> where Self: 'a;
unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
Some(T::new_temp_mut(obj?))
}
fn get_mut(&mut self) -> Self::Mutable<'_> {
Some(self.as_mut()?.get_mut())
}
fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
Some(self.as_pin_mut()?.get_mut_pinned())
}
}
unsafe impl<T: TempReprMutChk> TempReprMutChk for Option<T> {
type SwapChkData = Option<T::SwapChkData>;
fn swap_chk_data(&self) -> Self::SwapChkData {
self.as_ref().map(T::swap_chk_data)
}
}
macro_rules! impl_temp_repr_tuple {
($($idx:tt $T:ident),*) => {
#[allow(clippy::unused_unit)]
unsafe impl<$($T: TempRepr),*> TempRepr for ($($T,)*) {
type Shared<'a> = ($($T::Shared<'a>,)*) where Self: 'a;
#[allow(unused_variables)]
unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
($($T::new_temp(obj.$idx),)*)
}
fn get(&self) -> Self::Shared<'_> {
($(self.$idx.get(),)*)
}
}
#[allow(clippy::unused_unit)]
unsafe impl<$($T: TempReprMut),*> TempReprMut for ($($T,)*) {
type Mutable<'a> = ($($T::Mutable<'a>,)*) where Self: 'a;
#[allow(unused_variables)]
unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
($($T::new_temp_mut(obj.$idx),)*)
}
fn get_mut(&mut self) -> Self::Mutable<'_> {
($(self.$idx.get_mut(),)*)
}
#[allow(unused_variables)]
fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
unsafe {
let temp = self.get_unchecked_mut();
($(Pin::new_unchecked(&mut temp.$idx).get_mut_pinned(),)*)
}
}
}
#[allow(clippy::unused_unit)]
unsafe impl<$($T: TempReprMutChk),*> TempReprMutChk for ($($T,)*) {
type SwapChkData = ($($T::SwapChkData,)*);
fn swap_chk_data(&self) -> Self::SwapChkData {
($(self.$idx.swap_chk_data(),)*)
}
}
};
}
impl_temp_repr_tuple!();
impl_temp_repr_tuple!(0 T0);
impl_temp_repr_tuple!(0 T0, 1 T1);
impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2);
impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3);
impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4);
impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5);
impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6);
impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7);
impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8);
impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9);
impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9, 10 T10);
impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9, 10 T10, 11 T11);
#[cfg(feature = "either")]
unsafe impl<T0: TempRepr, T1: TempRepr> TempRepr for either::Either<T0, T1> {
type Shared<'a> = either::Either<T0::Shared<'a>, T1::Shared<'a>> where Self: 'a;
unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
match obj {
either::Either::Left(obj0) => either::Either::Left(T0::new_temp(obj0)),
either::Either::Right(obj1) => either::Either::Right(T1::new_temp(obj1)),
}
}
fn get(&self) -> Self::Shared<'_> {
match self {
either::Either::Left(self0) => either::Either::Left(self0.get()),
either::Either::Right(self1) => either::Either::Right(self1.get()),
}
}
}
#[cfg(feature = "either")]
unsafe impl<T0: TempReprMut, T1: TempReprMut> TempReprMut for either::Either<T0, T1> {
type Mutable<'a> = either::Either<T0::Mutable<'a>, T1::Mutable<'a>> where Self: 'a;
unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
match obj {
either::Either::Left(obj0) => either::Either::Left(T0::new_temp_mut(obj0)),
either::Either::Right(obj1) => either::Either::Right(T1::new_temp_mut(obj1)),
}
}
fn get_mut(&mut self) -> Self::Mutable<'_> {
match self {
either::Either::Left(self0) => either::Either::Left(self0.get_mut()),
either::Either::Right(self1) => either::Either::Right(self1.get_mut()),
}
}
fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
match self.as_pin_mut() {
either::Either::Left(self0) => either::Either::Left(self0.get_mut_pinned()),
either::Either::Right(self1) => either::Either::Right(self1.get_mut_pinned()),
}
}
}
#[cfg(feature = "either")]
unsafe impl<T0: TempReprMutChk, T1: TempReprMutChk> TempReprMutChk for either::Either<T0, T1> {
type SwapChkData = either::Either<T0::SwapChkData, T1::SwapChkData>;
fn swap_chk_data(&self) -> Self::SwapChkData {
match self {
either::Either::Left(self0) => either::Either::Left(self0.swap_chk_data()),
either::Either::Right(self1) => either::Either::Right(self1.swap_chk_data()),
}
}
}
unsafe impl<T: TempRepr> TempRepr for Range<T> {
type Shared<'a> = Range<T::Shared<'a>> where Self: 'a;
unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
T::new_temp(obj.start)..T::new_temp(obj.end)
}
fn get(&self) -> Self::Shared<'_> {
self.start.get()..self.end.get()
}
}
unsafe impl<T: TempReprMut> TempReprMut for Range<T> {
type Mutable<'a> = Range<T::Mutable<'a>> where Self: 'a;
unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
T::new_temp_mut(obj.start)..T::new_temp_mut(obj.end)
}
fn get_mut(&mut self) -> Self::Mutable<'_> {
self.start.get_mut()..self.end.get_mut()
}
fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
unsafe {
let temp = self.get_unchecked_mut();
let start = Pin::new_unchecked(&mut temp.start);
let end = Pin::new_unchecked(&mut temp.end);
start.get_mut_pinned()..end.get_mut_pinned()
}
}
}
unsafe impl<T: TempReprMutChk> TempReprMutChk for Range<T> {
type SwapChkData = Range<T::SwapChkData>;
fn swap_chk_data(&self) -> Self::SwapChkData {
self.start.swap_chk_data()..self.end.swap_chk_data()
}
}
unsafe impl<T: TempRepr> TempRepr for RangeFrom<T> {
type Shared<'a> = RangeFrom<T::Shared<'a>> where Self: 'a;
unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
T::new_temp(obj.start)..
}
fn get(&self) -> Self::Shared<'_> {
self.start.get()..
}
}
unsafe impl<T: TempReprMut> TempReprMut for RangeFrom<T> {
type Mutable<'a> = RangeFrom<T::Mutable<'a>> where Self: 'a;
unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
T::new_temp_mut(obj.start)..
}
fn get_mut(&mut self) -> Self::Mutable<'_> {
self.start.get_mut()..
}
fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
unsafe {
self.map_unchecked_mut(|temp| &mut temp.start)
.get_mut_pinned()..
}
}
}
unsafe impl<T: TempReprMutChk> TempReprMutChk for RangeFrom<T> {
type SwapChkData = RangeFrom<T::SwapChkData>;
fn swap_chk_data(&self) -> Self::SwapChkData {
self.start.swap_chk_data()..
}
}
unsafe impl<T: TempRepr> TempRepr for RangeTo<T> {
type Shared<'a> = RangeTo<T::Shared<'a>> where Self: 'a;
unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
..T::new_temp(obj.end)
}
fn get(&self) -> Self::Shared<'_> {
..self.end.get()
}
}
unsafe impl<T: TempReprMut> TempReprMut for RangeTo<T> {
type Mutable<'a> = RangeTo<T::Mutable<'a>> where Self: 'a;
unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
..T::new_temp_mut(obj.end)
}
fn get_mut(&mut self) -> Self::Mutable<'_> {
..self.end.get_mut()
}
fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
unsafe {
..self
.map_unchecked_mut(|temp| &mut temp.end)
.get_mut_pinned()
}
}
}
unsafe impl<T: TempReprMutChk> TempReprMutChk for RangeTo<T> {
type SwapChkData = RangeTo<T::SwapChkData>;
fn swap_chk_data(&self) -> Self::SwapChkData {
..self.end.swap_chk_data()
}
}
unsafe impl TempRepr for RangeFull {
type Shared<'a> = RangeFull where Self: 'a;
unsafe fn new_temp(_obj: RangeFull) -> Self {
..
}
fn get(&self) -> RangeFull {
..
}
}
impl AlwaysShared for RangeFull {}
unsafe impl TempReprMutChk for RangeFull {
type SwapChkData = RangeFull;
fn swap_chk_data(&self) -> Self::SwapChkData {
..
}
}
pub mod mapped {
use super::*;
pub trait HasTempRepr {
type Temp: TempRepr;
type Shared<'a>
where
Self: 'a;
fn shared_to_mapped(obj: Self::Shared<'_>) -> <Self::Temp as TempRepr>::Shared<'_>;
fn mapped_to_shared(mapped: <Self::Temp as TempRepr>::Shared<'_>) -> Self::Shared<'_>;
}
pub trait HasTempReprMut: HasTempRepr<Temp: TempReprMut> {
type Mutable<'a>
where
Self: 'a;
fn mut_to_mapped(obj: Self::Mutable<'_>) -> <Self::Temp as TempReprMut>::Mutable<'_>;
fn mapped_to_mut(mapped: <Self::Temp as TempReprMut>::Mutable<'_>) -> Self::Mutable<'_>;
}
pub trait IsAlwaysShared: HasTempRepr<Temp: AlwaysShared> {}
impl<T: IsAlwaysShared> HasTempReprMut for T {
type Mutable<'a> = Self::Shared<'a> where Self: 'a;
fn mut_to_mapped(obj: Self::Mutable<'_>) -> <Self::Temp as TempReprMut>::Mutable<'_> {
Self::shared_to_mapped(obj)
}
fn mapped_to_mut(mapped: <Self::Temp as TempReprMut>::Mutable<'_>) -> Self::Mutable<'_> {
Self::mapped_to_shared(mapped)
}
}
pub struct MappedTempRepr<T: HasTempRepr>(T::Temp);
unsafe impl<T: HasTempRepr> TempRepr for MappedTempRepr<T> {
type Shared<'a> = T::Shared<'a> where Self: 'a;
unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
MappedTempRepr(T::Temp::new_temp(T::shared_to_mapped(obj)))
}
fn get(&self) -> Self::Shared<'_> {
T::mapped_to_shared(self.0.get())
}
}
unsafe impl<T: HasTempReprMut> TempReprMut for MappedTempRepr<T> {
type Mutable<'a> = T::Mutable<'a> where Self: 'a;
unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
MappedTempRepr(T::Temp::new_temp_mut(T::mut_to_mapped(obj)))
}
fn get_mut(&mut self) -> Self::Mutable<'_> {
T::mapped_to_mut(self.0.get_mut())
}
fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
let temp = unsafe { self.map_unchecked_mut(|temp| &mut temp.0) };
T::mapped_to_mut(temp.get_mut_pinned())
}
}
unsafe impl<T: HasTempReprMut<Temp: TempReprMutChk>> TempReprMutChk for MappedTempRepr<T> {
type SwapChkData = <T::Temp as TempReprMutChk>::SwapChkData;
fn swap_chk_data(&self) -> Self::SwapChkData {
self.0.swap_chk_data()
}
}
impl<T: HasTempRepr> PartialEq for MappedTempRepr<T>
where
for<'a> T::Shared<'a>: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.get() == other.get()
}
}
impl<T: HasTempRepr> Eq for MappedTempRepr<T> where for<'a> T::Shared<'a>: Eq {}
impl<T: HasTempRepr> PartialOrd for MappedTempRepr<T>
where
for<'a> T::Shared<'a>: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.get().partial_cmp(&other.get())
}
fn lt(&self, other: &Self) -> bool {
self.get() < other.get()
}
fn le(&self, other: &Self) -> bool {
self.get() <= other.get()
}
fn gt(&self, other: &Self) -> bool {
self.get() > other.get()
}
fn ge(&self, other: &Self) -> bool {
self.get() >= other.get()
}
}
impl<T: HasTempRepr> Ord for MappedTempRepr<T>
where
for<'a> T::Shared<'a>: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
self.get().cmp(&other.get())
}
}
impl<T: HasTempRepr> Hash for MappedTempRepr<T>
where
for<'a> T::Shared<'a>: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
self.get().hash(state);
}
}
impl<T: HasTempRepr> Debug for MappedTempRepr<T>
where
for<'a> T::Shared<'a>: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.get().fmt(f)
}
}
impl<T: HasTempRepr> Display for MappedTempRepr<T>
where
for<'a> T::Shared<'a>: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.get().fmt(f)
}
}
impl<T> HasTempRepr for slice::Iter<'static, T> {
type Temp = TempRef<[T]>;
type Shared<'a> = slice::Iter<'a, T> where Self: 'a;
fn shared_to_mapped(obj: Self::Shared<'_>) -> <Self::Temp as TempRepr>::Shared<'_> {
obj.as_slice()
}
fn mapped_to_shared(mapped: <Self::Temp as TempRepr>::Shared<'_>) -> Self::Shared<'_> {
mapped.iter()
}
}
impl<T> IsAlwaysShared for slice::Iter<'static, T> {}
impl<T> HasTempRepr for slice::IterMut<'static, T> {
type Temp = TempRefMut<[T]>;
type Shared<'a> = slice::Iter<'a, T> where Self: 'a;
fn shared_to_mapped(obj: Self::Shared<'_>) -> <Self::Temp as TempRepr>::Shared<'_> {
obj.as_slice()
}
fn mapped_to_shared(mapped: <Self::Temp as TempRepr>::Shared<'_>) -> Self::Shared<'_> {
mapped.iter()
}
}
impl<T> HasTempReprMut for slice::IterMut<'static, T> {
type Mutable<'a> = slice::IterMut<'a, T> where Self: 'a;
fn mut_to_mapped(obj: Self::Mutable<'_>) -> <Self::Temp as TempReprMut>::Mutable<'_> {
obj.into_slice()
}
fn mapped_to_mut(mapped: <Self::Temp as TempReprMut>::Mutable<'_>) -> Self::Mutable<'_> {
mapped.iter_mut()
}
}
impl HasTempRepr for Chars<'static> {
type Temp = TempRef<str>;
type Shared<'a> = Chars<'a> where Self: 'a;
fn shared_to_mapped(obj: Self::Shared<'_>) -> <Self::Temp as TempRepr>::Shared<'_> {
obj.as_str()
}
fn mapped_to_shared(mapped: <Self::Temp as TempRepr>::Shared<'_>) -> Self::Shared<'_> {
mapped.chars()
}
}
impl IsAlwaysShared for Chars<'static> {}
}
pub type TempSliceIter<T> = MappedTempRepr<slice::Iter<'static, T>>;
pub type TempSliceIterMut<T> = MappedTempRepr<slice::IterMut<'static, T>>;
pub type TempChars = MappedTempRepr<Chars<'static>>;
#[cfg(test)]
mod tests {
use core::mem::swap;
use super::*;
#[cfg(feature = "std")]
fn init_tests() {
static INIT: std::sync::LazyLock<()> = std::sync::LazyLock::new(|| unsafe {
set_modification_panic_fn(|| {
if !std::thread::panicking() {
panic!("TempInstMut instance was modified");
}
})
});
*INIT
}
#[cfg(not(feature = "std"))]
fn init_tests() {}
#[test]
fn temp_ref() {
init_tests();
let mut a = 42;
let a_inst = TempInst::<TempRef<i32>>::new(&a);
let a_ref = a_inst.get();
assert_eq!(*a_ref, 42);
let double = 2 * *a_ref;
assert_eq!(a, 42);
a += 1; assert_eq!(a, 43);
assert_eq!(double, 2 * 42);
}
#[test]
fn temp_ref_call() {
init_tests();
let a = 42;
let double = TempInst::<TempRef<i32>>::call_with(&a, |a_inst| {
let a_ref = a_inst.get();
assert_eq!(*a_ref, 42);
2 * *a_ref
});
assert_eq!(a, 42);
assert_eq!(double, 2 * 42);
}
#[test]
fn temp_ref_call_pair() {
init_tests();
let a = 42;
let b = 23;
let sum = TempInst::<(TempRef<i32>, TempRef<i32>)>::call_with((&a, &b), |a_b_inst| {
let (a_ref, b_ref) = a_b_inst.get();
assert_eq!(*a_ref, 42);
assert_eq!(*b_ref, 23);
*a_ref + *b_ref
});
assert_eq!(a, 42);
assert_eq!(b, 23);
assert_eq!(sum, 42 + 23);
}
#[test]
fn temp_ref_call_mut() {
init_tests();
let mut a = 42;
let double = TempInstMut::<TempRefMut<i32>>::call_with(&mut a, |a_inst| {
let a_ref = a_inst.get_mut();
assert_eq!(*a_ref, 42);
*a_ref += 1;
2 * *a_ref
});
assert_eq!(a, 43);
assert_eq!(double, 2 * 43);
}
#[test]
fn temp_ref_call_pair_mut() {
init_tests();
let mut a = 42;
let mut b = 23;
let sum = TempInstMut::<(TempRefMut<i32>, TempRefMut<i32>)>::call_with(
(&mut a, &mut b),
|a_b_inst| {
let (a_ref, b_ref) = a_b_inst.get_mut();
assert_eq!(*a_ref, 42);
assert_eq!(*b_ref, 23);
*a_ref += 1;
*b_ref -= 2;
*a_ref + *b_ref
},
);
assert_eq!(a, 43);
assert_eq!(b, 21);
assert_eq!(sum, 43 + 21);
}
#[test]
fn temp_ref_call_pair_half_mut() {
init_tests();
let mut a = 42;
let b = 23;
let sum =
TempInstMut::<(TempRefMut<i32>, TempRef<i32>)>::call_with((&mut a, &b), |a_b_inst| {
let (a_ref, b_ref) = a_b_inst.get_mut();
assert_eq!(*a_ref, 42);
assert_eq!(*b_ref, 23);
*a_ref += 1;
*a_ref + *b_ref
});
assert_eq!(a, 43);
assert_eq!(b, 23);
assert_eq!(sum, 43 + 23);
}
#[test]
fn temp_ref_mut_pin() {
init_tests();
let mut a = 42;
let a_inst = pin!(TempInstPin::<TempRefMut<i32>>::new(&mut a));
let a_ref = a_inst.deref_pin().get_mut_pinned();
assert_eq!(*a_ref, 42);
*a_ref += 1;
let double = 2 * *a_ref;
assert_eq!(a, 43);
assert_eq!(double, 2 * 43);
}
#[test]
fn temp_ref_mut_call_pin() {
init_tests();
let mut a = 42;
let double = TempInstPin::<TempRefMut<i32>>::call_with(&mut a, |a_inst| {
let a_ref = a_inst.get_mut_pinned();
assert_eq!(*a_ref, 42);
*a_ref += 1;
2 * *a_ref
});
assert_eq!(a, 43);
assert_eq!(double, 2 * 43);
}
#[test]
fn temp_ref_pin_call_pin() {
init_tests();
let mut a = pin!(42);
let double = TempInstPin::<TempRefPin<i32>>::call_with(Pin::as_mut(&mut a), |a_inst| {
let a_ref = a_inst.get_mut_pinned().get_mut();
assert_eq!(*a_ref, 42);
*a_ref += 1;
2 * *a_ref
});
assert_eq!(*a, 43);
assert_eq!(double, 2 * 43);
}
#[cfg(feature = "std")]
#[test]
#[should_panic(expected = "TempInstMut instance was modified")]
fn temp_ref_call_mut_illegal_swap() {
init_tests();
let mut a = 42;
TempInstMut::<TempRefMut<i32>>::call_with(&mut a, |a_inst| {
let mut b = 43;
TempInstMut::<TempRefMut<i32>>::call_with(&mut b, |b_inst| {
swap(a_inst, b_inst);
});
let b_ref = a_inst.get_mut();
assert_ne!(*b_ref, 43);
});
}
#[test]
fn temp_ref_call_mut_swap_zero_size() {
init_tests();
let mut a = ((), ());
TempInstMut::<TempRefMut<()>>::call_with(&mut a.0, |a0_inst| {
TempInstMut::<TempRefMut<()>>::call_with(&mut a.1, |a1_inst| {
swap(a0_inst, a1_inst);
});
let a1_ref = &mut a.1;
let a1_ref_2 = a0_inst.get_mut();
*a1_ref = ();
*a1_ref_2 = ();
});
}
#[cfg(feature = "std")]
#[test]
fn temp_ref_send() {
init_tests();
let a = 42;
let a_inst = TempInst::<TempRef<i32>>::new(&a);
std::thread::scope(|scope| {
let thread = scope.spawn(move || **a_inst);
let result = thread.join().unwrap();
assert_eq!(result, 42);
});
}
#[cfg(feature = "std")]
#[test]
fn temp_ref_sync() {
init_tests();
let a = 42;
let a_inst = TempInst::<TempRef<i32>>::new(&a);
std::thread::scope(|scope| {
let thread = scope.spawn(|| **a_inst);
let result = thread.join().unwrap();
assert_eq!(result, 42);
});
}
#[cfg(feature = "std")]
#[test]
fn temp_ref_pin_send() {
init_tests();
let a = pin!(42);
let a_inst = TempInstPin::<TempRefPin<i32>>::new(a);
std::thread::scope(|scope| {
let thread = scope.spawn(move || **a_inst);
let result = thread.join().unwrap();
assert_eq!(result, 42);
});
}
#[cfg(feature = "std")]
#[test]
fn temp_ref_pin_sync() {
init_tests();
let a = pin!(42);
let a_inst = TempInstPin::<TempRefPin<i32>>::new(a);
std::thread::scope(|scope| {
let thread = scope.spawn(|| **a_inst);
let result = thread.join().unwrap();
assert_eq!(result, 42);
});
}
#[cfg(feature = "std")]
#[test]
fn temp_ref_call_mut_send() {
init_tests();
let mut a = 42;
TempInstMut::<TempRefMut<i32>>::call_with(&mut a, |a_inst| {
std::thread::scope(|scope| {
let thread = scope.spawn(move || **a_inst += 1);
thread.join().unwrap();
})
});
assert_eq!(a, 43);
}
#[cfg(feature = "std")]
#[test]
fn temp_ref_call_mut_sync() {
init_tests();
let mut a = 42;
TempInstMut::<TempRefMut<i32>>::call_with(&mut a, |a_inst| {
std::thread::scope(|scope| {
let thread = scope.spawn(|| **a_inst += 1);
thread.join().unwrap();
})
});
assert_eq!(a, 43);
}
}