use std::{marker::PhantomData, mem::MaybeUninit, ops::Deref};
use stable_deref_trait::CloneStableDeref;
use crate::{AnyRef, LifetimeDowncast, ReturnType};
pub struct AnyRefBuilder<'a, O>(O, PhantomData<&'a ()>);
impl<'a, O> AnyRefBuilder<'a, O>
where
O: CloneStableDeref + 'static,
{
#[inline]
pub(super) fn new(owner: O) -> Self {
AnyRefBuilder(owner, PhantomData)
}
pub fn build<T>(&mut self, holder: <T as ReturnType<'a>>::Target) -> AnyRef<T, O>
where
T: LifetimeDowncast + ?Sized,
{
unsafe {
let mut ar: MaybeUninit<AnyRef<T, O>> = MaybeUninit::uninit();
let ptr = ar.as_mut_ptr();
(&mut (*ptr).owner as *mut O).write(self.0.clone());
(&mut (*ptr).holder as *mut _ as *mut () as *mut <T as ReturnType<'a>>::Target)
.write(holder);
ar.assume_init()
}
}
}
pub fn build<O, F, R>(owner: O, func: F) -> R
where
O: CloneStableDeref + 'static,
F: for<'a> FnOnce(&'a <O as Deref>::Target, AnyRefBuilder<'a, O>) -> R,
{
let tar = unsafe { &*(&*owner as *const _) };
func(tar, AnyRefBuilder::new(owner))
}