feat(users/Profpatsch/netencode): add decoder module

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>
This commit is contained in:
Profpatsch 2021-01-29 15:55:11 +01:00
parent 06f4b75a18
commit 3877243211

View file

@ -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)))
}
}
}
}