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 { key_walker: K, value_walker: V, _tag: T, } impl KeyValueWalker { #[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 { Tag(TagError), Key(K), Value(V), } #[derive(Debug, SendSync)] pub struct KeyValueError(KeyValueErrorKind); impl<'ctx, T, K, V, E> crate::Walker<'ctx, E> for KeyValueWalker where E: Environment, T: TagKind, K: crate::Walker<'ctx, E> + 'ctx, V: crate::Walker<'ctx, E> + 'ctx, { type Error = KeyValueError; type Output = (); #[inline(always)] fn walk<'b: 'c, 'd: 'c, 'c>( self, visitor: DynVisitor<'b, 'd, 'ctx, E>, ) -> Canonical<'c, Result, E> { let Self { key_walker, value_walker, _tag, } = self; E::value(visitor) .update_map(key_walker, |key_walker, visitor| { visit_tag::(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::(self.tag, visitor.cast(), NoopWalker::new()).await { // Ok(VisitResult::Skipped(_)) => { // match visit_tag::, 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::, 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::, 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(()) // }) } }