use crate::walk::walkers::core::noop::NoopWalker; use effectful::{ bound::{Dynamic, No, SsBound}, effective::{Effective, Canonical}, environment::{Environment}, higher_ranked::{Rank1, WithLt}, SendSync, DynBind, }; use serde::{ de::{DeserializeSeed, MapAccess}, Deserializer, }; use crate::{ any::{type_name, AnyTrait, BorrowedStatic, OwnedStatic, TempBorrowedStatic}, hkt::Marker, protocol::{ visitor::{ request_hint, tags, visit_sequence, visit_tag, visit_value, EffectiveVisitExt as _, SequenceScope, Tag, TagConst, TagHint, TagKnown, Value, ValueKnown, VisitResult, }, walker::hint::{DynVisitorWith, Hint, HintMeta}, DynVisitor, DynWalker, }, walk::walkers::core::int::IntegerWalkerError, Flow, Walker, }; #[derive(SendSync)] pub struct DeserializerWalker<'ctx, T, E> where T: Deserializer<'ctx>, { inner: Inner<'ctx, T>, _marker: Marker, } #[derive(SendSync)] enum Inner<'ctx, T> where T: Deserializer<'ctx>, { Temp, Init(Dynamic), Error(DeserializerWalkerError<'ctx, T>), Done, } impl<'ctx, T, E: Environment> DeserializerWalker<'ctx, T, E> where T: Deserializer<'ctx>, { pub fn new(deserializer: T) -> Self { Self { inner: Inner::Init(Dynamic(deserializer)), _marker: Default::default(), } } } #[derive(SendSync)] 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, "u8 {}", err), VisitorError::u16(err) => write!(f, "u16 {}", err), VisitorError::u32(err) => write!(f, "u32 {}", err), VisitorError::u64(err) => write!(f, "u64 {}", err), VisitorError::u128(err) => write!(f, "u128 {}", err), VisitorError::usize(err) => write!(f, "usize {}", err), VisitorError::i8(err) => write!(f, "i8 {}", err), VisitorError::i16(err) => write!(f, "i16 {}", err), VisitorError::i32(err) => write!(f, "i32 {}", err), VisitorError::i64(err) => write!(f, "i64 {}", err), VisitorError::i128(err) => write!(f, "i128 {}", err), VisitorError::isize(err) => write!(f, "isize {}", err), VisitorError::Serde(err) => write!(f, "Serde {}", err.0), } } } 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: Environment> Walker<'ctx, E> for DeserializerWalker<'ctx, T, E> where T: Deserializer<'ctx>, E: SsBound, { type Error = DeserializerWalkerError<'ctx, T>; type Output = (); fn walk<'visitor: 'effect, 'lt: 'effect, 'effect>( self, visitor: DynVisitor<'visitor, 'lt, 'ctx, E>, ) -> Canonical<'effect, Result, E> where Self: 'effect, { E::value((self, visitor)) .update_map((), |_, (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::(visitor.cast(), DynWalker(this)) .map((), |_, x| VisitResult::unit_skipped(x)) .cast() }) .if_not_finished((), |_, (this, visitor)| { this.call_deserialize(visitor.cast(), |visitor, deserializer| { let x = deserializer.deserialize_any(Visitor::::new(visitor, "any")); x.map(|x| x.cast()) }) .cast() }) .map((), |_, ((this, _), _)| match this.inner { Inner::Temp => todo!(), Inner::Init(_) => todo!(), Inner::Error(err) => Err(err), Inner::Done => Ok(()), }) .cast() } } impl<'lt, 'ctx: 'lt, T: 'lt, E> AnyTrait<'lt, 'ctx> for DeserializerWalker<'ctx, T, E> where T: Deserializer<'ctx>, E: Environment, { } // any_trait! { // impl['ctx, T][E] DeserializerWalker<'ctx, T, E> = [ // HintProto, E>>, // HintProto, E>>, // HintProto, E>>, // HintProto, E>>, // HintProto, E>>, // HintProto, E>>, // HintProto, E>>, // HintProto, E>>, // HintProto, E>>, // HintProto, E>>, // HintProto, E>>, // HintProto, E>>, // HintProto>, // ] where // T: Deserializer<'ctx>, // E: Environment // } impl<'ctx, T, E: Environment> DeserializerWalker<'ctx, T, E> where T: Deserializer<'ctx>, E: SsBound, { #[allow(clippy::type_complexity)] fn call_deserialize<'this: 'e, 'e, Cap>( &'this mut self, cap: Cap, f: fn( Cap, T, ) -> Result< Canonical<'e, (Option>, VisitResult), E, (&'ctx (), Cap)>, T::Error, >, ) -> Canonical<'e, VisitResult, E> where 'ctx: 'this, Cap: DynBind + 'e, { match core::mem::replace(&mut self.inner, Inner::Temp) { Inner::Init(deserializer) => { // E::value(cap) // .update((HasSendAndSync(f), self, deserializer), |(HasSendAndSync(f), this, deserializer), cap| { match f(cap, deserializer.0) { Ok(eff) => eff .map(self, |this, result| match result { (None, result) => { // Return the flow the visitor decided on. this.inner = Inner::Done; result } (Some(err), _) => { this.inner = Inner::Error(DeserializerWalkerError { inner: err }); Flow::Err.into() } }) .cast(), Err(err) => { self.inner = Inner::Error(DeserializerWalkerError { inner: VisitorError::Serde(Dynamic(err)), }); E::value(Flow::Err.into()).cast() } } // }) // .map((), |_, (_, x)| x) // .cast() } inner => { // We really shouldn't be in this situation... self.inner = inner; E::value(VisitResult::Skipped(())).cast() } } } } macro_rules! impl_hints { (<$ctx:lifetime, $T:ident, $E:ident> $($proto:ty => $method:ident: $type:ty),* $(,)?) => { $(impl<$ctx, $T, $E: Environment> Hint<$ctx, type_name::Raised<'static, $ctx, $proto>> for DeserializerWalker<$ctx, $T, $E> where $T: Deserializer<$ctx>, $E: SsBound { fn hint<'this: 'e, 'visitor: 'e, 'lt: 'e, 'hint: 'e, 'e>( &'this mut self, visitor: DynVisitorWith<'visitor, 'lt, $ctx, type_name::Raised<'static, $ctx, $proto>>, _hint: WithLt<'hint, as HintMeta>::Hint>, ) -> Canonical<'e, VisitResult, $E> where $ctx: 'this + 'visitor + 'hint + 'e, { $E::value((self, visitor)) .update_map((), |_, (this, visitor)| { this.call_deserialize(visitor, move |visitor, deserializer| { let x = deserializer.$method(Visitor::<$T, $E>::new(visitor.cast(), stringify!($type))); x.map(|x| x.cast()) }) .cast() }) .map((), |_, (_, x)| x) .cast() } fn known<'a>( &'a mut self, _hint: &'a WithLt<'a, as HintMeta>::Hint>, ) -> Canonical<'a, Result as HintMeta>::Known>, ()>, $E> where WithLt<'a, as HintMeta>::Known>: DynBind<$E> { E::value(Ok(ValueKnown { preview: None })).cast() } })* }; } impl_hints! { <'ctx, T, E> dyn Value<'ctx, OwnedStatic, E> => deserialize_bool: bool, dyn Value<'ctx, OwnedStatic, E> => deserialize_i8: i8, dyn Value<'ctx, OwnedStatic, E> => deserialize_i16: i16, dyn Value<'ctx, OwnedStatic, E> => deserialize_i32: i32, dyn Value<'ctx, OwnedStatic, E> => deserialize_i64: i64, dyn Value<'ctx, OwnedStatic, E> => deserialize_i128: i128, dyn Value<'ctx, OwnedStatic, E> => deserialize_u8: u8, dyn Value<'ctx, OwnedStatic, E> => deserialize_u16: u16, dyn Value<'ctx, OwnedStatic, E> => deserialize_u32: u32, dyn Value<'ctx, OwnedStatic, E> => deserialize_u64: u64, dyn Value<'ctx, OwnedStatic, E> => deserialize_u128: u128, dyn Value<'ctx, OwnedStatic, E> => deserialize_f32: f32, dyn Value<'ctx, OwnedStatic, E> => deserialize_f64: f64, dyn Value<'ctx, OwnedStatic, E> => deserialize_char: char, dyn Value<'ctx, type_name::Raised<'static, 'ctx, TempBorrowedStatic<'static, str>>, E> => deserialize_str: &str, dyn Value<'ctx, type_name::Raised<'static, 'ctx, BorrowedStatic<'ctx, str>>, E> => deserialize_str: &str, dyn Value<'ctx, OwnedStatic, E> => deserialize_string: String, dyn Value<'ctx, type_name::Raised<'static, 'ctx, TempBorrowedStatic<'static, [u8]>>, E> => deserialize_bytes: &[u8], dyn Value<'ctx, type_name::Raised<'static, 'ctx, BorrowedStatic<'ctx, [u8]>>, E> => deserialize_bytes: &[u8], dyn Value<'ctx, OwnedStatic>, E> => deserialize_byte_buf: Vec, // ... } impl<'ctx, T, E: Environment> Hint<'ctx, type_name::Raised<'static, 'ctx, dyn Tag<'ctx, tags::Map, E>>> for DeserializerWalker<'ctx, T, E> where T: Deserializer<'ctx>, E: SsBound, { fn hint<'this: 'e, 'visitor: 'e, 'lt: 'e, 'hint: 'e, 'e>( &'this mut self, _visitor: DynVisitorWith< 'visitor, 'lt, 'ctx, type_name::Raised<'static, 'ctx, dyn Tag<'ctx, tags::Map, E>>, >, _hint: TagHint, ) -> Canonical<'e, VisitResult, E> where 'ctx: 'this + 'visitor + 'hint + 'e, { // self.call_deserialize(|deserializer| { // todo!() // }) E::value(VisitResult::Skipped(())).cast() } fn known<'a>( &'a mut self, _hint: &'a WithLt<'a, Rank1>>, ) -> Canonical<'a, Result>, ()>, E> where WithLt<'a, Rank1>: DynBind, { E::value(Ok(TagKnown { kind_available: Some(true), })) .cast() } } #[allow(non_camel_case_types, unused)] #[derive(SendSync)] enum VisitorError<'ctx, T> where T: Deserializer<'ctx>, { u8(IntegerWalkerError), u16(IntegerWalkerError), u32(IntegerWalkerError), u64(IntegerWalkerError), u128(IntegerWalkerError), usize(IntegerWalkerError), i8(IntegerWalkerError), i16(IntegerWalkerError), i32(IntegerWalkerError), i64(IntegerWalkerError), i128(IntegerWalkerError), isize(IntegerWalkerError), Serde(Dynamic), } #[derive(SendSync)] struct Visitor<'temp, 'lt, 'ctx, T, E: Environment> where T: Deserializer<'ctx>, { wanted: &'static str, visitor: DynVisitor<'temp, 'lt, 'ctx, E>, _marker: Marker<(T, E)>, } impl<'temp, 'lt, 'ctx, T, E: Environment> Visitor<'temp, 'lt, 'ctx, T, E> where T: Deserializer<'ctx>, { pub fn new(visitor: DynVisitor<'temp, 'lt, 'ctx, E>, wanted: &'static str) -> Self { Self { wanted, visitor, _marker: Default::default(), } } } macro_rules! impl_visits { (@owned $($method:ident: $type:ty),* $(,)?) => { $(fn $method(self, v: $type) -> Result where Err: serde::de::Error, { // Visit the treaty visitor with the value serde gave. Ok(visit_value::<_, E>(self.visitor, OwnedStatic(v)).map((), |_, result| (None, result.unit_skipped())).cast()) })* }; // 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(self, v: $type) -> Result where Err: serde::de::Error, { // This will attempt every native integer type until the visitor accepts one of them. Ok($crate::walk::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()) }).cast()) })* }; } impl<'temp, 'lt, 'ctx, T: Deserializer<'ctx> + 'temp, E: Environment> serde::de::Visitor<'ctx> for Visitor<'temp, 'lt, 'ctx, T, E> where E: SsBound, { type Value = Canonical<'temp, (Option>, VisitResult), E>; 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, // ... } 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, } fn visit_str(self, _v: &str) -> Result where Err: serde::de::Error, { todo!() } fn visit_map(self, map: A) -> Result where A: MapAccess<'ctx>, { E::value((self, MapScope { map: Dynamic(map) })).update_map((), |_, (this, scope)| { // Need to notify the visitor we are doing a map instead of just a sequence. let x = visit_tag::(TagConst, this.visitor.cast(), NoopWalker::new()).wait(); visit_sequence(this.visitor.cast(), scope).cast() }); Ok(E::value((None, VisitResult::Control(Flow::Done))).cast()) } } #[derive(SendSync)] struct MapScope { map: Dynamic, } impl<'ctx, A, E: Environment> SequenceScope<'ctx, E> for MapScope where E: SsBound, A: MapAccess<'ctx>, { fn size_hint(&mut self) -> Canonical<'_, (usize, Option), E> { E::value((0, self.map.0.size_hint())).cast() } fn next<'a: 'c, 'd: 'c, 'b: 'c, 'c>( &'a mut self, mut visitor: DynVisitor<'b, 'd, 'ctx, E>, ) -> Canonical<'c, Flow, E> where 'ctx: 'c + 'a + 'b, { // need to convert visitor into a serde key and value deserializer // match self.map.0.next_entry() { // Ok(Some((key, value))) => {}, // Ok(None) => {}, // Err(err) => {}, // } // let key = self.map.0.next_key(); // assume we have done this // let value = self.map.0.next_value_seed(()); // we want value here to be an // effective. let x = self.map.0.next_key_seed(KeyDeserialize { visitor: visitor.cast(), }); // dbg!(&x); if x.unwrap().is_some() { // There is another item. let _x = self.map.0.next_value_seed(ValueDeserialize { visitor }); // dbg!(x); E::value(Flow::Continue).cast() } else { E::value(Flow::Done).cast() } } } struct KeyDeserialize<'a, 'lt, 'ctx, E: Environment> { visitor: DynVisitor<'a, 'lt, 'ctx, E>, } impl<'a, 'lt, 'ctx: 'a, E: Environment> DeserializeSeed<'ctx> for KeyDeserialize<'a, 'lt, 'ctx, E> where E: SsBound, { type Value = (); fn deserialize(mut self, deserializer: D) -> Result where D: Deserializer<'ctx>, { // We have a deserializer and we know how to handle those! let walker = DeserializerWalker::<'_, _, E>::new(deserializer); // We can't return an effective that stores D as we don't know D's lifetime, // so we must block instead. This should be fine as serde itself isn't async // normally. let _x = visit_tag::(TagConst, self.visitor.cast(), walker) .map((), |_, result| match result { Ok(visit) => visit.unit_skipped(), Err(_) => Flow::Err.into(), }) .wait(); // dbg!(x); Ok(()) } } struct ValueDeserialize<'a, 'lt, 'ctx, E: Environment> { visitor: DynVisitor<'a, 'lt, 'ctx, E>, } impl<'a, 'lt, 'ctx, E: Environment> DeserializeSeed<'ctx> for ValueDeserialize<'a, 'lt, 'ctx, E> where E: SsBound, { type Value = (); fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'ctx>, { // We have a deserializer and we know how to handle those! let walker = DeserializerWalker::<'_, _, E>::new(deserializer); let _x = walker.walk(self.visitor).wait(); // dbg!(x); Ok(()) } }