use serde::Deserializer;
use crate::{
any::{BorrowedStaticHrt, OwnedStatic, TempBorrowedStatic, TempBorrowedStaticHrt, TypeName}, any_trait, effect::{
BlockOn, Effect, EffectExt as _, Effective as _, EffectiveExt as _, ErasedEffective, Ss,
}, hkt::Marker, protocol::{
visitor::{request_hint, visit_value, ValueKnown, ValueProto, VisitResult},
walker::hint::{DynVisitorWith, Hint, HintMeta, HintProto, MetaHint, MetaKnown},
DynVisitor, DynWalker,
}, walkers::core::int::IntegerWalkerError, Flow, Walker
};
pub struct DeserializerWalker<'ctx, T, E>
where
T: Deserializer<'ctx>,
{
inner: Inner<'ctx, T>,
_marker: Marker<E>,
}
enum Inner<'ctx, T>
where
T: Deserializer<'ctx>,
{
Temp,
Init(T),
Error(DeserializerWalkerError<'ctx, T>),
Done,
}
impl<'ctx, T, E: Effect> DeserializerWalker<'ctx, T, E>
where
T: Deserializer<'ctx>,
{
pub fn new(deserializer: T) -> Self {
Self {
inner: Inner::Init(deserializer),
_marker: Default::default(),
}
}
}
pub struct DeserializerWalkerError<'ctx, T>
where
T: Deserializer<'ctx>
{
inner: VisitorError<'ctx, T>,
}
impl<'ctx, T> core::fmt::Debug for DeserializerWalkerError<'ctx, T>
where
T: Deserializer<'ctx>
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match &self.inner {
VisitorError::u8(err) => write!(f, "{}", err),
VisitorError::u16(err) => write!(f, "{}", err),
VisitorError::u32(err) => write!(f, "{}", err),
VisitorError::u64(err) => write!(f, "{}", err),
VisitorError::u128(err) => write!(f, "{}", err),
VisitorError::usize(err) => write!(f, "{}", err),
VisitorError::i8(err) => write!(f, "{}", err),
VisitorError::i16(err) => write!(f, "{}", err),
VisitorError::i32(err) => write!(f, "{}", err),
VisitorError::i64(err) => write!(f, "{}", err),
VisitorError::i128(err) => write!(f, "{}", err),
VisitorError::isize(err) => write!(f, "{}", err),
VisitorError::Serde(err) => write!(f, "{}", err),
}
}
}
impl<'ctx, T> core::fmt::Display for DeserializerWalkerError<'ctx, T>
where
T: Deserializer<'ctx>
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:?}", self)
}
}
impl<'ctx, T, E: Effect> Walker<'ctx, E> for DeserializerWalker<'ctx, T, E>
where
T: Deserializer<'ctx> + Ss,
T::Error: Ss,
{
type Error = DeserializerWalkerError<'ctx, T>;
type Output = ();
fn walk<'visitor: 'effect, 'effect>(
self,
visitor: DynVisitor<'visitor, 'ctx>,
) -> ErasedEffective<'effect, Result<Self::Output, Self::Error>, E>
where
Self: 'effect,
{
E::as_ctx((self, visitor), |(this, visitor)| {
// Serde deserializers usually prefer that a hint method is called rather than _any.
// As such we need to ask the visitor for a hint first.
request_hint::<E>(visitor.cast(), DynWalker(this))
.map(VisitResult::unit_skipped)
.cast()
})
.map(|((this, _), _)| match this.inner {
Inner::Temp => todo!(),
Inner::Init(_) => todo!(),
Inner::Error(err) => Err(err),
Inner::Done => Ok(()),
})
}
}
any_trait! {
impl['ctx, T, E] DeserializerWalker<'ctx, T, E> = [
HintProto<ValueProto<OwnedStatic<bool>, E>>,
HintProto<ValueProto<OwnedStatic<i8>, E>>,
HintProto<ValueProto<OwnedStatic<i16>, E>>,
HintProto<ValueProto<OwnedStatic<i32>, E>>,
HintProto<ValueProto<OwnedStatic<i64>, E>>,
HintProto<ValueProto<OwnedStatic<i128>, E>>,
HintProto<ValueProto<OwnedStatic<u8>, E>>,
HintProto<ValueProto<OwnedStatic<u16>, E>>,
HintProto<ValueProto<OwnedStatic<u32>, E>>,
HintProto<ValueProto<OwnedStatic<u64>, E>>,
HintProto<ValueProto<OwnedStatic<u128>, E>>,
HintProto<ValueProto<OwnedStatic<char>, E>>,
] where
T: Deserializer<'ctx> + Ss,
T::Error: Ss,
E: Effect
}
impl<'ctx, T, E: Effect> DeserializerWalker<'ctx, T, E>
where
T: Deserializer<'ctx>,
{
fn call_deserialize<'visitor, 'e, F>(&mut self, f: F) -> ErasedEffective<'e, VisitResult, E>
where
F: FnOnce(T) -> Result<(Option<VisitorError<'ctx, T>>, VisitResult), T::Error>,
{
match core::mem::replace(&mut self.inner, Inner::Temp) {
Inner::Init(deserializer) => {
match f(deserializer) {
Ok((None, result)) => {
// Return the flow the visitor decided on.
self.inner = Inner::Done;
E::ready(result)
}
Ok((Some(err), _)) => {
self.inner = Inner::Error(DeserializerWalkerError { inner: err});
E::ready(Flow::Err.into())
}
Err(err) => {
// There was an error from serde so record it and signal an error with the
// flow.
self.inner = Inner::Error(DeserializerWalkerError { inner: VisitorError::Serde(err) });
E::ready(Flow::Err.into())
}
}
}
inner => {
// We really shouldn't be in this situation...
self.inner = inner;
E::ready(VisitResult::Skipped(()))
}
}
}
}
macro_rules! impl_hints {
(<$ctx:lifetime, $T:ident, $E:ident> $($proto:ty => $method:ident: $type:ty),* $(,)?) => {
$(impl<$ctx, $T, $E: Effect> Hint<$ctx, $proto> for DeserializerWalker<$ctx, $T, $E>
where
$T: Deserializer<$ctx>,
{
fn hint<'this: 'e, 'visitor: 'e, 'hint: 'e, 'e>(
&'this mut self,
visitor: DynVisitorWith<'visitor, $ctx, $proto>,
_hint: MetaHint<'hint, $ctx, $proto>,
) -> ErasedEffective<'e, VisitResult, $E>
where
$ctx: 'this + 'visitor + 'hint + 'e,
{
self.call_deserialize(|deserializer| deserializer.$method(Visitor::new(visitor, stringify!($type))))
}
fn known<'a>(
&'a mut self,
_hint: &'a MetaHint<'a, 'ctx, $proto>,
) -> ErasedEffective<'a, Result<MetaKnown<'a, 'ctx, $proto>, ()>, $E> {
E::ready(Ok(ValueKnown { preview: None }))
}
})*
};
}
impl_hints! {
<'ctx, T, E>
ValueProto<OwnedStatic<bool>, E> => deserialize_bool: bool,
ValueProto<OwnedStatic<i8>, E> => deserialize_i8: i8,
ValueProto<OwnedStatic<i16>, E> => deserialize_i16: i16,
ValueProto<OwnedStatic<i32>, E> => deserialize_i32: i32,
ValueProto<OwnedStatic<i64>, E> => deserialize_i64: i64,
ValueProto<OwnedStatic<i128>, E> => deserialize_i128: i128,
ValueProto<OwnedStatic<u8>, E> => deserialize_u8: u8,
ValueProto<OwnedStatic<u16>, E> => deserialize_u16: u16,
ValueProto<OwnedStatic<u32>, E> => deserialize_u32: u32,
ValueProto<OwnedStatic<u64>, E> => deserialize_u64: u64,
ValueProto<OwnedStatic<u128>, E> => deserialize_u128: u128,
ValueProto<OwnedStatic<f32>, E> => deserialize_f32: f32,
ValueProto<OwnedStatic<f64>, E> => deserialize_f64: f64,
ValueProto<OwnedStatic<char>, E> => deserialize_char: char,
ValueProto<TempBorrowedStaticHrt<str>, E> => deserialize_str: &str,
ValueProto<BorrowedStaticHrt<str>, E> => deserialize_str: &str,
ValueProto<OwnedStatic<String>, E> => deserialize_string: String,
ValueProto<TempBorrowedStaticHrt<[u8]>, E> => deserialize_bytes: &[u8],
ValueProto<BorrowedStaticHrt<[u8]>, E> => deserialize_bytes: &[u8],
ValueProto<OwnedStatic<Vec<u8>>, E> => deserialize_byte_buf: Vec<u8>,
// ...
}
#[allow(non_camel_case_types, unused)]
enum VisitorError<'ctx, T>
where
T: Deserializer<'ctx>
{
u8(IntegerWalkerError<u8>),
u16(IntegerWalkerError<u16>),
u32(IntegerWalkerError<u32>),
u64(IntegerWalkerError<u64>),
u128(IntegerWalkerError<u128>),
usize(IntegerWalkerError<usize>),
i8(IntegerWalkerError<i8>),
i16(IntegerWalkerError<i16>),
i32(IntegerWalkerError<i32>),
i64(IntegerWalkerError<i64>),
i128(IntegerWalkerError<i128>),
isize(IntegerWalkerError<isize>),
Serde(T::Error),
}
struct Visitor<'temp, 'ctx, T, E>
where
T: Deserializer<'ctx>
{
wanted: &'static str,
visitor: DynVisitor<'temp, 'ctx>,
error: Option<VisitorError<'ctx, T>>,
_marker: Marker<(T, E)>,
}
impl<'temp, 'ctx, T, E> Visitor<'temp, 'ctx, T, E>
where
T: Deserializer<'ctx>
{
pub fn new<Protocol: HintMeta<Effect = E>>(
visitor: DynVisitorWith<'temp, 'ctx, Protocol>,
wanted: &'static str,
) -> Self {
Self {
wanted,
visitor: visitor.into_inner(),
error: None,
_marker: Default::default(),
}
}
}
macro_rules! impl_visits {
(@owned $($method:ident: $type:ty),* $(,)?) => {
$(fn $method<Err>(mut self, v: $type) -> Result<Self::Value, Err>
where
Err: serde::de::Error,
{
// Visit the treaty visitor with the value serde gave.
let result = visit_value::<_, E>(self.visitor.cast(), OwnedStatic(v));
// Because serde is sync we need to block on the effective here.
// We use the block on impl the effect context says to use.
let value = E::BlockOn::block_on(result.into_future());
// If the visitor skipped the value we just report a continue.
Ok((self.error, value.unit_skipped()))
})*
};
// Many serde deserializers (like serde_json) don't follow the hint given when visiting.
// So we need to use the full integer walker that can visit all the types.
(@int $($method:ident: $type:ident),* $(,)?) => {
$(fn $method<Err>(mut self, v: $type) -> Result<Self::Value, Err>
where
Err: serde::de::Error,
{
let result = $crate::walkers::core::int::IntegerWalker::<_, E>::new(v).walk(self.visitor.cast());
// Because serde is sync we need to block on the effective here.
// We use the block on impl the effect context says to use.
if let Err(err) = E::BlockOn::block_on(result.into_future()) {
self.error = Some(VisitorError::$type(err))
}
Ok((self.error, VisitResult::Control(Flow::Done)))
})*
};
}
impl<'temp, 'ctx, T: Deserializer<'ctx>, E: Effect> serde::de::Visitor<'ctx> for Visitor<'temp, 'ctx, T, E> {
type Value = (Option<VisitorError<'ctx, T>>, VisitResult);
fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter.write_str(&self.wanted)
}
impl_visits! {
@owned
visit_bool: bool,
visit_char: char,
visit_string: String,
visit_byte_buf: Vec<u8>,
// ...
}
impl_visits! {
@int
visit_i8: i8,
visit_i16: i16,
visit_i32: i32,
visit_i64: i64,
visit_i128: i128,
visit_u8: u8,
visit_u16: u16,
visit_u32: u32,
visit_u64: u64,
visit_u128: u128,
}
}