From 42974ddd6494097bf8a85a123b8637115977dda4 Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Sat, 6 Feb 2021 20:31:56 +0100 Subject: feat(users/Profpatsch/netencode): nest Us in U::List MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Earlier we left the next level of values unencoded, since lists are just concatenated netencode values. But I noticed that you can’t write e.g. a `t_to_u` function, because only in the case of lists you need to allocate memory. Turns out that if we read the next level of values, everything is handled the same as in `Record` and things suddenly start working. We can also throw away some of the strange and ad-hoc parser helpers we needed before, `skip` and `list_take`, since now those are just normal `Vec::iter().skip()` and take. Change-Id: Ibc476e028102944a65c2b64621047086cfc09aa5 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2488 Reviewed-by: Profpatsch Tested-by: BuildkiteCI --- users/Profpatsch/netencode/netencode.rs | 50 ++++++++++++--------------------- 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/users/Profpatsch/netencode/netencode.rs b/users/Profpatsch/netencode/netencode.rs index 48a6c576b9d5..7f8506708de9 100644 --- a/users/Profpatsch/netencode/netencode.rs +++ b/users/Profpatsch/netencode/netencode.rs @@ -49,7 +49,7 @@ pub enum U<'a> { // Tags Sum(Tag<&'a str, U<'a>>), Record(Vec<(&'a str, U<'a>)>), - List(&'a [u8]), + List(Vec>), } #[derive(Debug, PartialEq, Eq, Clone)] @@ -106,8 +106,12 @@ pub fn encode(w: &mut W, u: U) -> std::io::Result<()> { write!(w, "}}") }, U::List(l) => { - write!(w, "[{}:", l.len())?; - w.write(l)?; + let mut c = std::io::Cursor::new(vec![]); + for u in l { + encode(&mut c, u)?; + } + write!(w, "[{}:", c.get_ref().len())?; + w.write(c.get_ref())?; write!(w, "]") } } @@ -268,29 +272,18 @@ pub mod parse { } fn list_t(s: &[u8]) -> IResult<&[u8], Vec> { - map_parser(list_g(), nom::multi::many0(t_t))(s) - } - - fn list_g() -> impl Fn(&[u8]) -> IResult<&[u8], &[u8]> { - sized('[', ']') - } - - fn skip() -> impl Fn(&[u8]) -> IResult<&[u8], ()> { - move |s: &[u8]| { - let (s, ()) = alt(( - // TODO: only use the sized parsers here - map(text, |_| ()), - map(unit_t, |_| ()), - map(list_g(), |_| ()), - map(t_t, |_| ()), - // TODO: add rest of parsers - ))(s)?; - Ok((s, ())) - } + list_g(t_t)(s) } - fn list_take<'a>(n: usize) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Vec>> { - map_parser(list_g(), nom::multi::many_m_n(n, n, u_u)) + fn list_g<'a, P, O>(inner: P) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Vec> + where + O: Clone, + P: Fn(&'a [u8]) -> IResult<&'a [u8], O> + { + map_parser( + sized('[', ']'), + nom::multi::many0(inner) + ) } fn record_t<'a>(s: &'a [u8]) -> IResult<&'a [u8], HashMap> { @@ -328,7 +321,7 @@ pub mod parse { map(binary_g(), U::Binary), map(unit_t, |()| U::Unit), map(tag_g(u_u), |t| U::Sum(t)), - map(list_g(), U::List), + map(list_g(u_u), U::List), map(record_g(u_u), U::Record), map(bool_t(), |u| U::N1(u)), @@ -493,13 +486,6 @@ pub mod parse { T::Unit, ])) ); - assert_eq!( - list_take(2)("[6:u,u,u,]".as_bytes()), - Ok(("".as_bytes(), vec![ - U::Unit, - U::Unit, - ])) - ); assert_eq!( list_t("[15:u,[7:t3:foo,]u,]".as_bytes()), Ok(("".as_bytes(), vec![ -- cgit 1.4.1