use effectful::{
effective::{Canonical, Effective},
environment::Environment,
SendSync,
};
use crate::{
protocol::{
visitor::{tags, visit_tag, EffectiveVisitExt as _, TagConst, TagError, TagKind},
DynVisitor,
},
Flow, Never,
};
#[derive(SendSync)]
pub struct KeyValueWalker<T, K, V> {
key_walker: K,
value_walker: V,
_tag: T,
}
impl<T, K, V> KeyValueWalker<T, K, V> {
#[inline(always)]
pub fn new(tag: T, key_walker: K, value_walker: V) -> Self {
Self {
key_walker,
value_walker,
_tag: tag,
}
}
}
#[derive(Debug, SendSync)]
#[allow(unused)]
enum KeyValueErrorKind<K, V> {
Tag(TagError<Never>),
Key(K),
Value(V),
}
#[derive(Debug, SendSync)]
pub struct KeyValueError<K, V>(KeyValueErrorKind<K, V>);
impl<'ctx, T, K, V, E> crate::Walker<'ctx, E> for KeyValueWalker<T, K, V>
where
E: Environment,
T: TagKind<E>,
K: crate::Walker<'ctx, E> + 'ctx,
V: crate::Walker<'ctx, E> + 'ctx,
{
type Error = KeyValueError<K::Error, V::Error>;
type Output = ();
#[inline(always)]
fn walk<'b: 'c, 'd: 'c, 'c>(
self,
visitor: DynVisitor<'b, 'd, 'ctx, E>,
) -> Canonical<'c, Result<Self::Output, Self::Error>, E> {
let Self {
key_walker,
value_walker,
_tag,
} = self;
E::value(visitor)
.update_map(key_walker, |key_walker, visitor| {
visit_tag::<tags::Key, E, _>(TagConst, visitor.cast(), key_walker)
.map((), |_, result| match result {
Ok(visit) => visit.unit_skipped(),
Err(_) => Flow::Err.into(),
})
.cast()
})
.if_not_finished(value_walker, |value_walker, visitor| {
value_walker
.walk(visitor.cast())
.map((), |_, result| match result {
Ok(_) => Flow::Done.into(),
Err(_err) => Flow::Err.into(),
})
.cast()
})
.map((), |_, _| Ok(()))
.cast()
// E::wrap(async move {
// match visit_tag::<T, E, _>(self.tag, visitor.cast(), NoopWalker::new()).await {
// Ok(VisitResult::Skipped(_)) => {
// match visit_tag::<TagConst<{ TAG_KEY_VALUE.to_int() }>, E, _>(
// TagConst,
// visitor.cast(),
// NoopWalker::new(),
// )
// .await
// {
// Ok(VisitResult::Skipped(_) | VisitResult::Control(Flow::Continue)) => {}
// Ok(VisitResult::Control(_flow)) => return Ok(()),
// Err(_) => todo!(),
// }
// }
// Ok(VisitResult::Control(Flow::Continue)) => {}
// Ok(VisitResult::Control(_flow)) => todo!(),
// Err(_) => todo!(),
// }
//
// match visit_tag::<TagConst<{ TAG_KEY.to_int() }>, E, _>(
// TagConst,
// visitor.cast(),
// self.key_walker,
// )
// .await
// {
// Ok(VisitResult::Skipped(_) | VisitResult::Control(Flow::Continue)) => {}
// Ok(VisitResult::Control(_flow)) => return Ok(()),
// Err(_) => todo!(),
// }
//
// match visit_tag::<TagConst<{ TAG_VALUE.to_int() }>, E, _>(
// TagConst,
// visitor.cast(),
// self.value_walker,
// )
// .await
// {
// Ok(VisitResult::Control(Flow::Continue)) => {}
// Ok(VisitResult::Skipped(value_walker)) => {
// // Fallback to just walking the value.
// match value_walker.walk(visitor).await {
// Ok(_) => {}
// Err(_err) => todo!(),
// }
// }
// Ok(VisitResult::Control(_flow)) => todo!(),
// Err(_) => todo!(),
// }
//
// Ok(())
// })
}
}