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<E>,
}
#[derive(SendSync)]
enum Inner<'ctx, T>
where
T: Deserializer<'ctx>,
{
Temp,
Init(Dynamic<T>),
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<NeedSend = No, NeedSync = No>,
{
type Error = DeserializerWalkerError<'ctx, T>;
type Output = ();
fn walk<'visitor: 'effect, 'lt: 'effect, 'effect>(
self,
visitor: DynVisitor<'visitor, 'lt, 'ctx, E>,
) -> Canonical<'effect, Result<Self::Output, Self::Error>, 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::<E>(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::<T, E>::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<NeedSend = No, NeedSync = No>,
{
}
// 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>>,
// HintProto<TagProto<tags::Map, E>>,
// ] where
// T: Deserializer<'ctx>,
// E: Environment<NeedSend = No, NeedSync = No>
// }
impl<'ctx, T, E: Environment> DeserializerWalker<'ctx, T, E>
where
T: Deserializer<'ctx>,
E: SsBound<NeedSend = No, NeedSync = No>,
{
#[allow(clippy::type_complexity)]
fn call_deserialize<'this: 'e, 'e, Cap>(
&'this mut self,
cap: Cap,
f: fn(
Cap,
T,
) -> Result<
Canonical<'e, (Option<VisitorError<'ctx, T>>, VisitResult), E, (&'ctx (), Cap)>,
T::Error,
>,
) -> Canonical<'e, VisitResult, E>
where
'ctx: 'this,
Cap: DynBind<E> + '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<NeedSend = No, NeedSync = No>
{
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, <type_name::Raised<'static, $ctx, $proto> 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, <type_name::Raised<'static, $ctx, $proto> as HintMeta>::Hint>,
) -> Canonical<'a, Result<WithLt<'a, <type_name::Raised<'static, $ctx, $proto> as HintMeta>::Known>, ()>, $E>
where
WithLt<'a, <type_name::Raised<'static, $ctx, $proto> as HintMeta>::Known>: DynBind<$E>
{
E::value(Ok(ValueKnown { preview: None })).cast()
}
})*
};
}
impl_hints! {
<'ctx, T, E>
dyn Value<'ctx, OwnedStatic<bool>, E> => deserialize_bool: bool,
dyn Value<'ctx, OwnedStatic<i8>, E> => deserialize_i8: i8,
dyn Value<'ctx, OwnedStatic<i16>, E> => deserialize_i16: i16,
dyn Value<'ctx, OwnedStatic<i32>, E> => deserialize_i32: i32,
dyn Value<'ctx, OwnedStatic<i64>, E> => deserialize_i64: i64,
dyn Value<'ctx, OwnedStatic<i128>, E> => deserialize_i128: i128,
dyn Value<'ctx, OwnedStatic<u8>, E> => deserialize_u8: u8,
dyn Value<'ctx, OwnedStatic<u16>, E> => deserialize_u16: u16,
dyn Value<'ctx, OwnedStatic<u32>, E> => deserialize_u32: u32,
dyn Value<'ctx, OwnedStatic<u64>, E> => deserialize_u64: u64,
dyn Value<'ctx, OwnedStatic<u128>, E> => deserialize_u128: u128,
dyn Value<'ctx, OwnedStatic<f32>, E> => deserialize_f32: f32,
dyn Value<'ctx, OwnedStatic<f64>, E> => deserialize_f64: f64,
dyn Value<'ctx, OwnedStatic<char>, 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<String>, 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<Vec<u8>>, E> => deserialize_byte_buf: Vec<u8>,
// ...
}
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<NeedSend = No, NeedSync = No>,
{
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<tags::Map>,
) -> 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<TagHint<tags::Map>>>,
) -> Canonical<'a, Result<WithLt<'a, Rank1<TagKnown>>, ()>, E>
where
WithLt<'a, Rank1<TagKnown>>: DynBind<E>,
{
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<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(Dynamic<T::Error>),
}
#[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<Err>(self, v: $type) -> Result<Self::Value, Err>
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<Err>(self, v: $type) -> Result<Self::Value, Err>
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<NeedSend = No, NeedSync = No>,
{
type Value = Canonical<'temp, (Option<VisitorError<'ctx, T>>, 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<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,
}
fn visit_str<Err>(self, _v: &str) -> Result<Self::Value, Err>
where
Err: serde::de::Error,
{
todo!()
}
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
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::<tags::Map, E, _>(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<A> {
map: Dynamic<A>,
}
impl<'ctx, A, E: Environment> SequenceScope<'ctx, E> for MapScope<A>
where
E: SsBound<NeedSend = No, NeedSync = No>,
A: MapAccess<'ctx>,
{
fn size_hint(&mut self) -> Canonical<'_, (usize, Option<usize>), 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<NeedSend = No, NeedSync = No>,
{
type Value = ();
fn deserialize<D>(mut self, deserializer: D) -> Result<Self::Value, D::Error>
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::<tags::Key, E, _>(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<NeedSend = No, NeedSync = No>,
{
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
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(())
}
}