about summary refs log tree commit diff
path: root/users/Profpatsch/netencode/netencode.rs
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2021-01-29T14·55+0100
committerProfpatsch <mail@profpatsch.de>2021-01-31T11·10+0000
commit38772432118cfc6818f9fac1f6d1e424c075e527 (patch)
treeae08e92a95fb9049a417c57bdc1b6d6a764e6b36 /users/Profpatsch/netencode/netencode.rs
parent06f4b75a183d0a4d2ebdac275c7fb097a6526efa (diff)
feat(users/Profpatsch/netencode): add decoder module r/2172
Decoders are implemented not directly on output types, but on trivial
proxy types, so that we can easily combine those into a decoder, and
then the associated type is the actual return value of the decoder.

Change-Id: Ibce98fa09fc944e02ab327112ec7ffbc09815830
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2455
Tested-by: BuildkiteCI
Reviewed-by: Profpatsch <mail@profpatsch.de>
Diffstat (limited to 'users/Profpatsch/netencode/netencode.rs')
-rw-r--r--users/Profpatsch/netencode/netencode.rs46
1 files changed, 46 insertions, 0 deletions
diff --git a/users/Profpatsch/netencode/netencode.rs b/users/Profpatsch/netencode/netencode.rs
index 3c6c113df589..66f3245fcf99 100644
--- a/users/Profpatsch/netencode/netencode.rs
+++ b/users/Profpatsch/netencode/netencode.rs
@@ -563,3 +563,49 @@ pub mod parse {
 
     }
 }
+
+pub mod dec {
+    use super::*;
+    use std::collections::HashMap;
+
+    pub struct DecodeError(pub String);
+
+    pub trait Decoder {
+        type A;
+        fn dec(T) -> Result<Self::A, DecodeError>;
+    }
+
+    pub struct ScalarAsBytes;
+
+    impl Decoder for ScalarAsBytes {
+        type A = Vec<u8>;
+        fn dec(t: T) -> Result<Self::A, DecodeError> {
+            match t {
+                T::N3(u) => Ok(format!("{}", u).into_bytes()),
+                T::N6(u) => Ok(format!("{}", u).into_bytes()),
+                T::N7(u) => Ok(format!("{}", u).into_bytes()),
+                T::I3(i) => Ok(format!("{}", i).into_bytes()),
+                T::I6(i) => Ok(format!("{}", i).into_bytes()),
+                T::I7(i) => Ok(format!("{}", i).into_bytes()),
+                T::Text(t) => Ok(t.into_bytes()),
+                T::Binary(b) => Ok(b),
+                o => Err(DecodeError(format!("Cannot decode {:?} into scalar", o))),
+            }
+        }
+    }
+
+    pub struct Record<T>(pub T);
+
+    impl<Inner: Decoder> Decoder for Record<Inner> {
+        type A = HashMap<String, Inner::A>;
+        fn dec(t: T) -> Result<Self::A, DecodeError> {
+            match t {
+                T::Record(map) =>
+                    map.into_iter()
+                    .map(|(k, v)| Inner::dec(v).map(|v2| (k, v2)))
+                    .collect::<Result<Self::A, _>>(),
+                o => Err(DecodeError(format!("Cannot decode {:?} into record", o)))
+            }
+        }
+    }
+}