use core::marker::PhantomData;
use crate::{
buffer::Buffer,
deserialize::{Deserialize, DeserializeError, Deserializer},
formula::{reference_size, BareFormula, Formula},
serialize::{field_size_hint, write_ref, write_reference, Serialize, Sizes},
};
pub struct Ref<F: ?Sized> {
marker: PhantomData<fn(&F) -> &F>,
}
impl<F> Formula for Ref<F>
where
F: BareFormula + ?Sized,
{
const MAX_STACK_SIZE: Option<usize> = Some(reference_size::<F>());
const EXACT_SIZE: bool = true;
const HEAPLESS: bool = matches!(F::MAX_STACK_SIZE, Some(0));
}
impl<F, T> Serialize<Ref<F>> for T
where
F: BareFormula + ?Sized,
T: Serialize<F>,
{
#[inline(always)]
fn serialize<B>(self, sizes: &mut Sizes, mut buffer: B) -> Result<(), B::Error>
where
B: Buffer,
{
let size = write_ref::<F, T, _>(self, sizes, buffer.reborrow())?;
write_reference::<F, B>(size, sizes.heap, sizes.heap, sizes.stack, buffer)?;
sizes.stack += reference_size::<F>();
Ok(())
}
#[inline(always)]
fn size_hint(&self) -> Option<Sizes> {
let mut sizes = field_size_hint::<F>(self, true)?;
sizes.to_heap(0);
sizes.add_stack(reference_size::<F>());
Some(sizes)
}
}
impl<'de, F, T> Deserialize<'de, Ref<F>> for T
where
F: BareFormula + ?Sized,
T: Deserialize<'de, F> + ?Sized,
{
#[inline(always)]
fn deserialize(de: Deserializer<'de>) -> Result<T, DeserializeError>
where
T: Sized,
{
let de = de.deref::<F>()?;
<T as Deserialize<F>>::deserialize(de)
}
#[inline(always)]
fn deserialize_in_place(&mut self, de: Deserializer<'de>) -> Result<(), DeserializeError> {
let de = de.deref::<F>()?;
<T as Deserialize<F>>::deserialize_in_place(self, de)
}
}