remove block on from deserializer visitor
Konnor Andrews 2024-06-11
parent d4755b8 · commit 90073a5
-rw-r--r--src/walk/walkers/serde/deserializer.rs118
-rw-r--r--tests/serde_deserializer.rs3
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);
}