From 7d9c30ab3d9a9cb72cfcdec0ef060059edca7b1e Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Sun, 7 Feb 2021 19:06:51 +0100 Subject: feat(users/Profpatsch/netencode): add `dec::RecordDot` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `dec::RecordDot` accesses a specific field of a netencode record. In order to implement this, either we’d have to introduce a type-level string, but in all honesty this kind of typelevel circlejerking never leads anywhere, so let’s change the trait to use `&self` after all. Usage is pretty much the same, except actually more like you’d expect. Change-Id: I5a7f1a3f587256c50df1b65c2969e5a7194bba70 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2494 Tested-by: BuildkiteCI Reviewed-by: Profpatsch --- users/Profpatsch/netencode/default.nix | 2 +- users/Profpatsch/netencode/netencode.rs | 33 ++++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) (limited to 'users/Profpatsch') diff --git a/users/Profpatsch/netencode/default.nix b/users/Profpatsch/netencode/default.nix index 31cd822061b6..3b62c8aaac59 100644 --- a/users/Profpatsch/netencode/default.nix +++ b/users/Profpatsch/netencode/default.nix @@ -108,7 +108,7 @@ let let mut buf = vec![]; let u = netencode::u_from_stdin_or_die_user_error("record-splice-env", &mut buf); let (_, prog) = exec_helpers::args_for_exec("record-splice-env", 0); - match Record::::dec(u) { + match Record(ScalarAsBytes).dec(u) { Ok(map) => { exec_helpers::exec_into_args("record-splice-env", prog, map); }, diff --git a/users/Profpatsch/netencode/netencode.rs b/users/Profpatsch/netencode/netencode.rs index e15cd8b38327..7099506f6df2 100644 --- a/users/Profpatsch/netencode/netencode.rs +++ b/users/Profpatsch/netencode/netencode.rs @@ -601,10 +601,12 @@ pub mod dec { pub trait Decoder<'a> { type A; - fn dec(u: U<'a>) -> Result; + fn dec(&self, u: U<'a>) -> Result; } + #[derive(Clone, Copy)] pub struct AnyT; + #[derive(Clone, Copy)] pub struct AnyU; // impl Decoder for AnyT { @@ -617,16 +619,17 @@ pub mod dec { impl<'a> Decoder<'a> for AnyU { type A = U<'a>; - fn dec(u: U<'a>) -> Result { + fn dec(&self, u: U<'a>) -> Result { Ok(u) } } + #[derive(Clone, Copy)] pub struct ScalarAsBytes; impl<'a> Decoder<'a> for ScalarAsBytes { type A = Vec; - fn dec(u: U<'a>) -> Result { + fn dec(&self, u: U<'a>) -> Result { match u { U::N3(u) => Ok(format!("{}", u).into_bytes()), U::N6(u) => Ok(format!("{}", u).into_bytes()), @@ -641,21 +644,41 @@ pub mod dec { } } + #[derive(Clone, Copy)] pub struct Record(pub T); impl<'a, Inner: Decoder<'a>> Decoder<'a> for Record { type A = HashMap<&'a str, Inner::A>; - fn dec(u: U<'a>) -> Result { + fn dec(&self, u: U<'a>) -> Result { match u { U::Record(map) => map.into_iter() - .map(|(k, v)| Inner::dec(v).map(|v2| (k, v2))) + .map(|(k, v)| self.0.dec(v).map(|v2| (k, v2))) .collect::>(), o => Err(DecodeError(format!("Cannot decode {:?} into record", o))) } } } + #[derive(Clone, Copy)] + pub struct RecordDot<'a, T> { + field: &'a str, + inner: T + } + + impl <'a, Inner: Decoder<'a> + Copy> Decoder<'a> for RecordDot<'_, Inner> { + type A = Inner::A; + fn dec(&self, u: U<'a>) -> Result { + match Record(self.inner).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))), + }, + Err(err) => Err(err), + } + } + } + fn dec_u(b: &[u8]) -> Result { match parse::u_u(b) { Ok((b"", u)) => Ok(u), -- cgit 1.4.1