feat(users/Profpatsch/netencode): add dec::{Text,Binary,OneOf}

`Text` and `Binary` should be self-explaining, they just match on the
primitive and throw an error otherwise.

OneOf is cool, because it allows the user to match on the
result type of decoding `inner`, and give a list of values that should
be allowed as the result type (the associated type `A` in the
`Decoder` trait).

Change-Id: Ia252e25194610555c17c37640a96953142f0a165
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2498
Tested-by: BuildkiteCI
Reviewed-by: Profpatsch <mail@profpatsch.de>
This commit is contained in:
Profpatsch 2021-02-09 01:36:00 +01:00
parent 8ff77f0b9f
commit fd0d0764ec

View file

@ -3,6 +3,7 @@ extern crate exec_helpers;
use std::collections::HashMap;
use std::io::{Write, Read};
use std::fmt::{Display, Debug};
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum T {
@ -21,6 +22,7 @@ pub enum T {
// Text
// TODO: make into &str
Text(String),
// TODO: rename to Bytes
Binary(Vec<u8>),
// Tags
// TODO: make into &str
@ -31,7 +33,7 @@ pub enum T {
}
impl T {
fn to_u<'a>(&'a self) -> U<'a> {
pub fn to_u<'a>(&'a self) -> U<'a> {
match self {
T::Unit => U::Unit,
T::N1(b) => U::N1(*b),
@ -649,6 +651,32 @@ pub mod dec {
}
}
#[derive(Clone, Copy)]
pub struct Text;
// TODO: rename to Bytes
#[derive(Clone, Copy)]
pub struct Binary;
impl<'a> Decoder<'a> for Text {
type A = &'a str;
fn dec(&self, u: U<'a>) -> Result<Self::A, DecodeError> {
match u {
U::Text(t) => Ok(t),
other => Err(DecodeError(format!("Cannot decode {:?} into Text", other))),
}
}
}
impl<'a> Decoder<'a> for Binary {
type A = &'a [u8];
fn dec(&self, u: U<'a>) -> Result<Self::A, DecodeError> {
match u {
U::Binary(b) => Ok(b),
other => Err(DecodeError(format!("Cannot decode {:?} into Binary", other))),
}
}
}
#[derive(Clone, Copy)]
pub struct ScalarAsBytes;
@ -672,7 +700,9 @@ pub mod dec {
#[derive(Clone, Copy)]
pub struct Record<T>(pub T);
impl<'a, Inner: Decoder<'a>> Decoder<'a> for Record<Inner> {
impl<'a, Inner> Decoder<'a> for Record<Inner>
where Inner: Decoder<'a>
{
type A = HashMap<&'a str, Inner::A>;
fn dec(&self, u: U<'a>) -> Result<Self::A, DecodeError> {
match u {
@ -687,14 +717,16 @@ pub mod dec {
#[derive(Clone, Copy)]
pub struct RecordDot<'a, T> {
field: &'a str,
inner: T
pub field: &'a str,
pub inner: T
}
impl <'a, Inner: Decoder<'a> + Copy> Decoder<'a> for RecordDot<'_, Inner> {
impl <'a, Inner> Decoder<'a> for RecordDot<'_, Inner>
where Inner: Decoder<'a> + Clone
{
type A = Inner::A;
fn dec(&self, u: U<'a>) -> Result<Self::A, DecodeError> {
match Record(self.inner).dec(u) {
match Record(self.inner.clone()).dec(u) {
Ok(mut map) => match map.remove(self.field) {
Some(inner) => Ok(inner),
None => Err(DecodeError(format!("Cannot find `{}` in record map", self.field))),
@ -704,6 +736,28 @@ pub mod dec {
}
}
#[derive(Clone)]
pub struct OneOf<T, A>{
pub inner: T,
pub list: Vec<A>,
}
impl <'a, Inner> Decoder<'a> for OneOf<Inner, Inner::A>
where Inner: Decoder<'a>,
Inner::A: Display + Debug + PartialEq
{
type A = Inner::A;
fn dec(&self, u: U<'a>) -> Result<Self::A, DecodeError> {
match self.inner.dec(u) {
Ok(inner) => match self.list.iter().any(|x| x.eq(&inner)) {
true => Ok(inner),
false => Err(DecodeError(format!("{} is not one of {:?}", inner, self.list)))
},
Err(err) => Err(err)
}
}
}
fn dec_u(b: &[u8]) -> Result<U, DecodeError> {
match parse::u_u(b) {
Ok((b"", u)) => Ok(u),