use crate::{Binding, Sever, TrySever, shroud::Shroud};
use core::{
marker::PhantomData,
ptr::{self, NonNull},
};
pub struct Raw;
pub type Soul<'a> = crate::Soul<'a, Raw>;
pub type Lich<T> = crate::Lich<T, Raw>;
pub type Pair<'a, T> = crate::Pair<'a, T, Raw>;
pub struct Data<T: ?Sized>(NonNull<T>);
pub struct Life<'a>(NonNull<()>, PhantomData<&'a ()>);
unsafe impl<'a, T: ?Sized + 'a> Send for Data<T> where &'a T: Send {}
unsafe impl<'a, T: ?Sized + 'a> Sync for Data<T> where &'a T: Sync {}
impl<T: ?Sized> TrySever for Data<T> {
fn try_sever(&mut self) -> Option<bool> {
Some(sever_panic())
}
}
impl Sever for Life<'_> {
fn sever(&mut self) -> bool {
sever_panic()
}
}
impl Binding for Raw {
type Data<T: ?Sized> = Data<T>;
type Life<'a> = Life<'a>;
fn are_bound<'a, T: ?Sized>(data: &Self::Data<T>, life: &Self::Life<'a>) -> bool {
ptr::addr_eq(data.0.as_ptr(), life.0.as_ptr())
}
fn is_life_bound(_: &Self::Life<'_>) -> bool {
true
}
fn is_data_bound<T: ?Sized>(_: &Self::Data<T>) -> bool {
true
}
}
impl<T: ?Sized> Lich<T> {
pub unsafe fn borrow(&self) -> &T {
unsafe { self.0.0.as_ref() }
}
}
pub fn ritual<'a, T: ?Sized + 'a, S: Shroud<T> + ?Sized + 'a>(value: &'a T) -> Pair<'a, S> {
let pointer = S::shroud(value);
(
crate::Lich(Data(pointer)),
crate::Soul(Life(pointer.cast(), PhantomData)),
)
}
pub fn redeem<'a, T: ?Sized + 'a>(lich: Lich<T>, soul: Soul<'a>) -> Result<(), Pair<'a, T>> {
crate::redeem::<_, _, false>(lich, soul).map(|_| {})
}
fn sever_panic() -> bool {
#[cfg(feature = "std")]
if std::thread::panicking() {
return false;
}
#[cfg(not(feature = "std"))]
{
use core::sync::atomic::{AtomicBool, Ordering};
static PANIC: AtomicBool = AtomicBool::new(false);
if PANIC.swap(true, Ordering::Relaxed) {
return false;
}
}
panic!("this `Lich<T, Raw>` must be redeemed")
}