remove block on from deserializer visitor
| -rw-r--r-- | src/walk/walkers/serde/deserializer.rs | 118 | ||||
| -rw-r--r-- | tests/serde_deserializer.rs | 3 |
2 files changed, 66 insertions, 55 deletions
diff --git a/src/walk/walkers/serde/deserializer.rs b/src/walk/walkers/serde/deserializer.rs index f5d9628..5a481e0 100644 --- a/src/walk/walkers/serde/deserializer.rs +++ b/src/walk/walkers/serde/deserializer.rs @@ -1,13 +1,19 @@ use serde::Deserializer; use crate::{ - any::{BorrowedStaticHrt, OwnedStatic, TempBorrowedStatic, TempBorrowedStaticHrt, TypeName}, any_trait, effect::{ + any::{BorrowedStaticHrt, OwnedStatic, TempBorrowedStatic, TempBorrowedStaticHrt, TypeName}, + any_trait, + effect::{ BlockOn, Effect, EffectExt as _, Effective as _, EffectiveExt as _, ErasedEffective, Ss, - }, hkt::Marker, protocol::{ + }, + 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 + }, + walkers::core::int::IntegerWalkerError, + Flow, Walker, }; pub struct DeserializerWalker<'ctx, T, E> @@ -40,16 +46,16 @@ where } } -pub struct DeserializerWalkerError<'ctx, T> +pub struct DeserializerWalkerError<'ctx, T> where - T: Deserializer<'ctx> + T: Deserializer<'ctx>, { inner: VisitorError<'ctx, T>, } -impl<'ctx, T> core::fmt::Debug for DeserializerWalkerError<'ctx, T> +impl<'ctx, T> core::fmt::Debug for DeserializerWalkerError<'ctx, T> where - T: Deserializer<'ctx> + T: Deserializer<'ctx>, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match &self.inner { @@ -70,9 +76,9 @@ where } } -impl<'ctx, T> core::fmt::Display for DeserializerWalkerError<'ctx, T> +impl<'ctx, T> core::fmt::Display for DeserializerWalkerError<'ctx, T> where - T: Deserializer<'ctx> + T: Deserializer<'ctx>, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{:?}", self) @@ -81,7 +87,7 @@ where impl<'ctx, T, E: Effect> Walker<'ctx, E> for DeserializerWalker<'ctx, T, E> where - T: Deserializer<'ctx> + Ss, + T: Deserializer<'ctx> + Ss + 'ctx, T::Error: Ss, { type Error = DeserializerWalkerError<'ctx, T>; @@ -126,35 +132,47 @@ any_trait! { HintProto<ValueProto<OwnedStatic<u128>, E>>, HintProto<ValueProto<OwnedStatic<char>, E>>, ] where - T: Deserializer<'ctx> + Ss, + T: Deserializer<'ctx> + Ss + 'ctx, T::Error: Ss, E: Effect } impl<'ctx, T, E: Effect> DeserializerWalker<'ctx, T, E> where - T: Deserializer<'ctx>, + T: Deserializer<'ctx> + Ss + 'ctx, + T::Error: Ss, { - fn call_deserialize<'visitor, 'e, F>(&mut self, f: F) -> ErasedEffective<'e, VisitResult, E> + fn call_deserialize<'visitor: 'e, 'e, F>( + &'e mut self, + f: F, + ) -> ErasedEffective<'e, VisitResult, E> where - F: FnOnce(T) -> Result<(Option<VisitorError<'ctx, T>>, VisitResult), T::Error>, + 'ctx: 'visitor, + F: FnOnce( + T, + ) -> Result< + ErasedEffective<'visitor, (Option<VisitorError<'ctx, T>>, VisitResult), E>, + 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()) - } + Ok(eff) => eff.map(|result| match result { + (None, result) => { + // Return the flow the visitor decided on. + self.inner = Inner::Done; + result + } + (Some(err), _) => { + self.inner = Inner::Error(DeserializerWalkerError { inner: err }); + 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) }); + self.inner = Inner::Error(DeserializerWalkerError { + inner: VisitorError::Serde(err), + }); E::ready(Flow::Err.into()) } } @@ -172,7 +190,8 @@ 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>, + $T: Deserializer<$ctx> + Ss + $ctx, + $T::Error: Ss, { fn hint<'this: 'e, 'visitor: 'e, 'hint: 'e, 'e>( &'this mut self, @@ -223,7 +242,7 @@ impl_hints! { #[allow(non_camel_case_types, unused)] enum VisitorError<'ctx, T> where - T: Deserializer<'ctx> + T: Deserializer<'ctx>, { u8(IntegerWalkerError<u8>), u16(IntegerWalkerError<u16>), @@ -242,17 +261,16 @@ where struct Visitor<'temp, 'ctx, T, E> where - T: Deserializer<'ctx> + 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> +impl<'temp, 'ctx, T, E> Visitor<'temp, 'ctx, T, E> where - T: Deserializer<'ctx> + T: Deserializer<'ctx>, { pub fn new<Protocol: HintMeta<Effect = E>>( visitor: DynVisitorWith<'temp, 'ctx, Protocol>, @@ -261,7 +279,6 @@ where Self { wanted, visitor: visitor.into_inner(), - error: None, _marker: Default::default(), } } @@ -269,43 +286,36 @@ where macro_rules! impl_visits { (@owned $($method:ident: $type:ty),* $(,)?) => { - $(fn $method<Err>(mut self, v: $type) -> Result<Self::Value, Err> + $(fn $method<Err>(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())) + Ok(visit_value::<_, E>(self.visitor, OwnedStatic(v)).map(|result| (None, result.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> + $(fn $method<Err>(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))) + // This will attempt every native integer type until the visitor accepts one of them. + Ok($crate::walkers::core::int::IntegerWalker::<_, E>::new(v).walk(self.visitor).map(|result| match result { + Ok(_) => (None, Flow::Done.into()), + Err(err) => (Some(VisitorError::$type(err)), Flow::Err.into()) + })) })* }; } -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); +impl<'temp, 'ctx, T: Deserializer<'ctx> + 'temp, E: Effect> serde::de::Visitor<'ctx> + for Visitor<'temp, 'ctx, T, E> +where + T::Error: Ss, +{ + type Value = ErasedEffective<'temp, (Option<VisitorError<'ctx, T>>, VisitResult), E>; fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { formatter.write_str(&self.wanted) diff --git a/tests/serde_deserializer.rs b/tests/serde_deserializer.rs index 4b7bc94..0b4bd79 100644 --- a/tests/serde_deserializer.rs +++ b/tests/serde_deserializer.rs @@ -17,7 +17,8 @@ fn demo() { fn demo2() { let x = json!(42); - let y = u8::build(DeserializerWalker::new(x)); + let mut de = serde_json::Deserializer::from_str("42"); + let y = u8::build(DeserializerWalker::new(&mut de)); assert_eq!(y.unwrap(), 42); } |