Diffstat (limited to 'src/walk/walkers/core/key_value.rs')
-rw-r--r--src/walk/walkers/core/key_value.rs92
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(())
+ })
+ }
+}