use std::{ptr, rc::Rc, sync::Arc};
use crate::{
Cloner, DeepClone,
dyn_clone::sealed::{Private, Sealed},
};
pub trait DynDeepClone: Sealed {
#[doc(hidden)]
fn __deep_clone_box(&self, cloner: &mut Cloner, _: Private) -> *mut ();
}
pub(crate) fn deep_clone_box<T>(value: &T, cloner: &mut Cloner) -> Box<T>
where
T: ?Sized + DynDeepClone,
{
let mut fat_ptr = ptr::from_ref(value);
unsafe {
let data_ptr = ptr::addr_of_mut!(fat_ptr).cast::<*mut ()>();
assert_eq!(*data_ptr as *const (), ptr::from_ref(value).cast::<()>());
*data_ptr = T::__deep_clone_box(value, cloner, Private);
}
unsafe { Box::from_raw(fat_ptr as *mut T) }
}
pub fn deep_clone_unsized_arc<T>(src: &Arc<T>, cloner: &mut Cloner) -> Arc<T>
where
T: ?Sized + DynDeepClone + 'static,
{
cloner.arc_unsized(src, |cloner| Arc::from(deep_clone_box(&**src, cloner)))
}
pub fn deep_clone_unsized_rc<T>(src: &Rc<T>, cloner: &mut Cloner) -> Rc<T>
where
T: ?Sized + DynDeepClone + 'static,
{
cloner.rc_unsized(src, |cloner| Rc::from(deep_clone_box(&**src, cloner)))
}
impl<T: DeepClone> DynDeepClone for T {
fn __deep_clone_box(&self, cloner: &mut Cloner, _: Private) -> *mut () {
Box::<T>::into_raw(Box::new(self.deep_clone_in(cloner))).cast::<()>()
}
}
#[expect(unnameable_types, reason = "being unnameable is what seals the trait")]
mod sealed {
#[derive(Debug)]
pub struct Private;
pub trait Sealed {}
impl<T: crate::DeepClone> Sealed for T {}
}