use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
use crate::State;
use crate::arena::ArenaBox;
use crate::de::{Sink, SinkHandle, Slot};
use crate::ser::boxed::unsize;
use crate::ser::{Boxed, Emit, Erased, IndexedSeq, MapEmitter, SeqEmitter};
#[repr(transparent)]
pub(crate) struct Adapted<A, T: ?Sized> {
_adapter: PhantomData<fn() -> A>,
value: T,
}
impl<A, T: ?Sized> Adapted<A, T> {
#[inline(always)]
pub(crate) fn new(value: &T) -> &Adapted<A, T> {
unsafe { &*(value as *const T as *const Adapted<A, T>) }
}
#[inline(always)]
pub(crate) fn get(&self) -> &T {
&self.value
}
}
impl<A, T> Adapted<A, T> {
#[inline(always)]
pub(crate) fn owned(value: T) -> Adapted<A, T> {
Adapted {
_adapter: PhantomData,
value,
}
}
#[inline(always)]
pub(crate) fn erased<'a>(value: &'a T) -> &'a (dyn Erased + 'a)
where
Adapted<A, T>: Erased,
{
let value: *const (dyn Erased + '_) = value as *const T as *const Adapted<A, T>;
unsafe {
&*core::mem::transmute::<*const (dyn Erased + '_), *const (dyn Erased + 'a)>(value)
}
}
#[inline(always)]
pub(crate) fn indexed<'a>(value: &'a T) -> &'a (dyn IndexedSeq + 'a)
where
Adapted<A, T>: IndexedSeq,
{
let value: *const (dyn IndexedSeq + '_) = value as *const T as *const Adapted<A, T>;
unsafe {
&*core::mem::transmute::<*const (dyn IndexedSeq + '_), *const (dyn IndexedSeq + 'a)>(
value,
)
}
}
}
impl<A, T: ?Sized> Deref for Adapted<A, T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
&self.value
}
}
impl<A, T: ?Sized> DerefMut for Adapted<A, T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut T {
&mut self.value
}
}
#[inline(always)]
pub(crate) fn slot_sink<'a, 'de, T, A>(out: &'a mut Option<T>) -> SinkHandle<'a, 'de>
where
Slot<T, A>: Sink<'de>,
{
let sink: *mut (dyn Sink<'de> + '_) = out as *mut Option<T> as *mut Slot<T, A>;
SinkHandle::to(unsafe {
&mut *core::mem::transmute::<*mut (dyn Sink<'de> + '_), *mut (dyn Sink<'de> + 'a)>(sink)
})
}
#[inline(always)]
pub(crate) fn arena_sink<'a, 'de, A, S: 'a>(sink: S, state: &mut State) -> SinkHandle<'a, 'de>
where
Adapted<A, S>: Sink<'de>,
{
let sink = ArenaBox::into_raw(ArenaBox::new(
Adapted::<A, S>::owned(sink),
&mut state.arena,
));
let sink: *mut (dyn Sink<'de> + '_) = sink.as_ptr();
let sink = unsafe {
ArenaBox::from_raw(core::mem::transmute::<
*mut (dyn Sink<'de> + '_),
*mut (dyn Sink<'de> + 'a),
>(sink))
};
SinkHandle::from_arena(sink)
}
#[inline(always)]
pub(crate) fn seq_emitter<'a, A, E: 'a>(emitter: E, state: &mut State) -> Emit<'a>
where
Adapted<A, E>: SeqEmitter,
{
let emitter = unsize(Boxed::arena(Adapted::<A, E>::owned(emitter), state), |x| {
x as *mut (dyn SeqEmitter + '_)
});
Emit::Seq(unsafe {
core::mem::transmute::<Boxed<dyn SeqEmitter + '_>, Boxed<dyn SeqEmitter + 'a>>(emitter)
})
}
#[inline(always)]
pub(crate) fn map_emitter<'a, A, E: 'a>(emitter: E, state: &mut State) -> Emit<'a>
where
Adapted<A, E>: MapEmitter,
{
let emitter = unsize(Boxed::arena(Adapted::<A, E>::owned(emitter), state), |x| {
x as *mut (dyn MapEmitter + '_)
});
Emit::Map(unsafe {
core::mem::transmute::<Boxed<dyn MapEmitter + '_>, Boxed<dyn MapEmitter + 'a>>(emitter)
})
}