about summary refs log tree commit diff
path: root/users/Profpatsch/netencode/netencode.rs
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2021-02-06T21·33+0100
committerProfpatsch <mail@profpatsch.de>2021-02-06T21·38+0000
commite207785e1fc78d06381b369c3b71b7e6becdbf80 (patch)
tree4dd97017f89a1a3e6f5e2fe3d20fd2536ec3d050 /users/Profpatsch/netencode/netencode.rs
parent7d28f121c7baba31f5bd731de8aff023fa23bdc0 (diff)
feat(users/Profpatsch/{netencode,http-parse}): use HashMap r/2186
`U::Record` is required to be a hash map (later keys should be
ignored), so why not do the hash map immediately.

This surfaced a problem with read-http, because duplicate headers in
http are possible, but before they’d be silently ignored.
Now we merge them into a `U::List` in case, to be handled by
consumers of read-http.

Change-Id: Ifd594916f76e5acf9d08e705e0dec2c10a0081c9
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2490
Tested-by: BuildkiteCI
Reviewed-by: Profpatsch <mail@profpatsch.de>
Diffstat (limited to 'users/Profpatsch/netencode/netencode.rs')
-rw-r--r--users/Profpatsch/netencode/netencode.rs17
1 files changed, 9 insertions, 8 deletions
diff --git a/users/Profpatsch/netencode/netencode.rs b/users/Profpatsch/netencode/netencode.rs
index 7f8506708d..09f347b786 100644
--- a/users/Profpatsch/netencode/netencode.rs
+++ b/users/Profpatsch/netencode/netencode.rs
@@ -48,7 +48,7 @@ pub enum U<'a> {
     Binary(&'a [u8]),
     // Tags
     Sum(Tag<&'a str, U<'a>>),
-    Record(Vec<(&'a str, U<'a>)>),
+    Record(HashMap<&'a str, U<'a>>),
     List(Vec<U<'a>>),
 }
 
@@ -290,14 +290,11 @@ pub mod parse {
         let (s, r) = record_g(t_t)(s)?;
         Ok((s,
             r.into_iter()
-            // ignore duplicated tag names that appear later
-            // by reverting the vector now
-            .rev()
             .map(|(k, v)| (k.to_string(), v))
             .collect::<HashMap<_,_>>()))
     }
 
-    fn record_g<'a, P, O>(inner: P) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Vec<(&'a str, O)>>
+    fn record_g<'a, P, O>(inner: P) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], HashMap<&'a str, O>>
     where
         O: Clone,
         P: Fn(&'a [u8]) -> IResult<&'a [u8], O>
@@ -306,9 +303,13 @@ pub mod parse {
             sized('{', '}'),
             nom::multi::fold_many1(
                 tag_g(inner),
-                Vec::new(),
-                |mut acc: Vec<_>, Tag { tag, mut val }| {
-                    acc.push((tag, *val));
+                HashMap::new(),
+                |mut acc: HashMap<_,_>, Tag { tag, mut val }| {
+                    // ignore duplicated tag names that appear later
+                    // according to netencode spec
+                    if ! acc.contains_key(tag) {
+                        acc.insert(tag, *val);
+                    }
                     acc
                 }
             )