Diffstat (limited to 'src/walk/walkers/core/key_value.rs')
| -rw-r--r-- | src/walk/walkers/core/key_value.rs | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/walk/walkers/core/key_value.rs b/src/walk/walkers/core/key_value.rs new file mode 100644 index 0000000..3ac5b6b --- /dev/null +++ b/src/walk/walkers/core/key_value.rs @@ -0,0 +1,92 @@ +use crate::{never::Never, WalkerTypes, effect::{Effect, Future}, protocol::{Visitor, visitor::{tag::{visit_tag, TagKind, TagConst, TagError}, Status}}, walkers::core::noop::NoopWalker, TAG_KEY_VALUE, Flow, TAG_KEY, TAG_VALUE}; + +pub struct KeyValueWalker<T, K, V> { + key_walker: K, + value_walker: V, + tag: T, +} + +impl<T, K, V> KeyValueWalker<T, K, V> { + pub fn new(tag: T, key_walker: K, value_walker: V) -> Self { + Self { + key_walker, + value_walker, + tag, + } + } +} + +#[derive(Debug)] +enum KeyValueErrorKind<K, V> { + Tag(TagError<Never>), + Key(K), + Value(V), +} + +#[derive(Debug)] +pub struct KeyValueError<K, V>(KeyValueErrorKind<K, V>); + +impl<T, K, V> WalkerTypes for KeyValueWalker<T, K, V> +where + K: WalkerTypes, + V: WalkerTypes, +{ + type Error = KeyValueError<K::Error, V::Error>; + + type Output = (); +} + +impl<'ctx, T, K, V, E> crate::Walker<'ctx, E> for KeyValueWalker<T, K, V> +where + E: Effect<'ctx>, + T: TagKind, + K: crate::Walker<'ctx, E>, + V: crate::Walker<'ctx, E>, +{ + fn walk<'a>( + self, + visitor: Visitor<'a, 'ctx>, + ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E> + where + Self: 'a + { + E::wrap(async move { + match visit_tag::<T, E, _>(self.tag, visitor, NoopWalker::new()).await { + Ok(Status::Skipped(_)) => { + match visit_tag::<TagConst<{ TAG_KEY_VALUE.to_int() }>, E, _>(TagConst, visitor, NoopWalker::new()).await + { + Ok(Status::Skipped(_) | Status::Flow(Flow::Continue)) => {}, + Ok(Status::Flow(flow)) => return Ok(()), + Err(_) => todo!(), + } + } + Ok(Status::Flow(Flow::Continue)) => {}, + Ok(Status::Flow(flow)) => todo!(), + Err(_) => todo!(), + } + + match visit_tag::<TagConst<{ TAG_KEY.to_int() }>, E, _>(TagConst, visitor, self.key_walker).await + { + Ok(Status::Skipped(_) | Status::Flow(Flow::Continue)) => {}, + Ok(Status::Flow(flow)) => return Ok(()), + Err(_) => todo!(), + } + + match visit_tag::<TagConst<{ TAG_VALUE.to_int() }>, E, _>(TagConst, visitor, self.value_walker).await + { + Ok(Status::Flow(Flow::Continue)) => {}, + Ok(Status::Skipped(value_walker)) => { + // Fallback to just walking the value. + match value_walker.walk(visitor).await { + Ok(_) => {}, + Err(err) => todo!(), + } + }, + Ok(Status::Flow(flow)) => todo!(), + Err(_) => todo!(), + } + + Ok(()) + }) + } +} |