)]}'
{"id":"depot~5108","triplet_id":"depot~canon~Ife9593956f4718e5e720f4f348c227e4f3a71e2d","project":"depot","branch":"canon","attention_set":{},"removed_from_attention_set":{"1000013":{"account":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"last_update":"2022-01-31 09:43:08.000000000","reason":"Profpatsch replied on the change"}},"hashtags":[],"change_id":"Ife9593956f4718e5e720f4f348c227e4f3a71e2d","subject":"feat(users/Profpatsch/netencode): ignore earlier record entries","status":"MERGED","created":"2022-01-29 12:00:57.000000000","updated":"2022-02-14 14:12:19.000000000","submitted":"2022-02-14 14:12:19.000000000","submitter":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"total_comment_count":2,"unresolved_comment_count":0,"has_review_started":true,"submission_id":"5108","meta_rev_id":"fc24b710438271498adebb6d4aa2558d896c5b60","_number":5108,"virtual_id_number":5108,"owner":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"actions":{},"labels":{"Code-Review":{"approved":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"all":[{"tag":"autogenerated:gerrit:merged","value":2,"date":"2022-02-14 14:12:19.000000000","permitted_voting_range":{"min":2,"max":2},"_account_id":1000034,"name":"sterni","email":"sternenseemann@systemli.org","username":"sterni"},{"value":0,"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},{"tag":"autogenerated:gerrit:merged","value":2,"date":"2022-02-14 14:12:19.000000000","permitted_voting_range":{"min":2,"max":2},"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"}],"values":{"-2":"This shall not be merged","-1":"I would prefer this is not merged as is"," 0":"No score","+1":"Looks good to me, but someone else must approve","+2":"Looks good to me, approved"},"description":"","default_value":0},"Verified":{"approved":{"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},"all":[{"value":0,"_account_id":1000034,"name":"sterni","email":"sternenseemann@systemli.org","username":"sterni"},{"tag":"autogenerated:gerrit:merged","value":1,"date":"2022-02-14 14:12:19.000000000","permitted_voting_range":{"min":1,"max":1},"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},{"value":0,"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"}],"values":{"-1":"Fails"," 0":"No score","+1":"Verified"},"description":"","default_value":0},"Autosubmit":{"approved":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"all":[{"value":0,"_account_id":1000034,"name":"sterni","email":"sternenseemann@systemli.org","username":"sterni"},{"value":0,"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},{"tag":"autogenerated:gerrit:merged","value":1,"date":"2022-02-14 14:12:19.000000000","_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"}],"values":{" 0":"Submit manually","+1":"Submit automatically"},"description":"","default_value":0,"optional":true},"All-Comments-Resolved":{"approved":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"all":[{"value":0,"_account_id":1000034,"name":"sterni","email":"sternenseemann@systemli.org","username":"sterni"},{"value":0,"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},{"value":0,"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"}]},"Conformant-Commit-Message":{"approved":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"all":[{"value":0,"_account_id":1000034,"name":"sterni","email":"sternenseemann@systemli.org","username":"sterni"},{"value":0,"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},{"value":0,"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"}]}},"removable_reviewers":[],"reviewers":{"REVIEWER":[{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},{"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},{"_account_id":1000034,"name":"sterni","email":"sternenseemann@systemli.org","username":"sterni"}]},"pending_reviewers":{},"reviewer_updates":[{"updated":"2022-01-29 12:01:04.000000000","updated_by":{"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},"reviewer":{"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},"state":"CC"},{"updated":"2022-01-29 12:02:55.000000000","updated_by":{"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},"reviewer":{"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},"state":"REVIEWER"},{"updated":"2022-01-29 12:03:07.000000000","updated_by":{"_account_id":1000034,"name":"sterni","email":"sternenseemann@systemli.org","username":"sterni"},"reviewer":{"_account_id":1000034,"name":"sterni","email":"sternenseemann@systemli.org","username":"sterni"},"state":"REVIEWER"}],"messages":[{"id":"84bc45fa7ed5596b8eb5b9e31003833d8f909183","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"date":"2022-01-29 12:00:57.000000000","message":"Uploaded patch set 1.","accounts_in_message":[],"_revision_number":1},{"id":"1e820dfabae8c697802871a75e79a983a18e2ca2","tag":"autogenerated:buildkite~trigger","author":{"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},"date":"2022-01-29 12:01:04.000000000","message":"Patch Set 1:\n\nStarted build for patchset #1 on: https://buildkite.com/tvl/depot/builds/12133","accounts_in_message":[],"_revision_number":1},{"id":"996be12a283cc000c30ea9ba47344dccd066accf","author":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"date":"2022-01-29 12:02:25.000000000","message":"Patch Set 1: Code-Review+2","accounts_in_message":[],"_revision_number":1},{"id":"182f2793dade03cbe092c2cc9c442f0a7fea443d","tag":"autogenerated:buildkite~result","author":{"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},"date":"2022-01-29 12:02:55.000000000","message":"Patch Set 1: Verified+1\n\nBuild of patchset 1 passed: https://buildkite.com/tvl/depot/builds/12133","accounts_in_message":[],"_revision_number":1},{"id":"f16372ec71bf916a6fbc4961c115b49bf1d56c23","author":{"_account_id":1000034,"name":"sterni","email":"sternenseemann@systemli.org","username":"sterni"},"date":"2022-01-29 12:03:07.000000000","message":"Patch Set 1: Code-Review+2","accounts_in_message":[],"_revision_number":1},{"id":"e29657b8928178fe68a86c679215496c669f799d","author":{"_account_id":1000034,"name":"sterni","email":"sternenseemann@systemli.org","username":"sterni"},"date":"2022-01-29 12:05:57.000000000","message":"Patch Set 1:\n\n(1 comment)","accounts_in_message":[],"_revision_number":1},{"id":"433e4ecdadb740fa276e6214b11ec3e8a49d70e4","author":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"date":"2022-01-31 09:43:08.000000000","message":"Patch Set 1: Autosubmit+1\n\n(1 comment)","accounts_in_message":[],"_revision_number":1},{"id":"cf468b7d337d4ea36dadd231ddf6f772dc3cf3cf","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"date":"2022-02-14 14:09:54.000000000","message":"Uploaded patch set 2.","accounts_in_message":[],"_revision_number":2},{"id":"0743b5c6d2aacd03faa0ed9e98c137375d288e4c","tag":"autogenerated:buildkite~trigger","author":{"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},"date":"2022-02-14 14:09:56.000000000","message":"Patch Set 2:\n\nStarted build for patchset #2 on: https://buildkite.com/tvl/depot/builds/12615","accounts_in_message":[],"_revision_number":2},{"id":"202b9f640b48d89090d3e2073b4efc3f693abd95","tag":"autogenerated:buildkite~result","author":{"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]},"date":"2022-02-14 14:11:34.000000000","message":"Patch Set 2: Verified+1\n\nBuild of patchset 2 passed: https://buildkite.com/tvl/depot/builds/12615","accounts_in_message":[],"_revision_number":2},{"id":"fc24b710438271498adebb6d4aa2558d896c5b60","tag":"autogenerated:gerrit:merged","author":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"date":"2022-02-14 14:12:19.000000000","message":"Change has been successfully rebased and submitted as ed68ba675191bc3da57019b14609deb713247821\n\n1 is the latest approved patch-set.\nThe change was submitted with unreviewed changes in the following files:\n\nThe name of the file: users/Profpatsch/netencode/netencode.rs\nInsertions: 8, Deletions: 5.\n\n```\n@@ -0:1 @@\n-  extern crate nom;\n\n@@ +1:2 @@\n+  extern crate nom;\n\n@@ -4:6, +4:6 @@\n-  use std::io::{Write, Read};\n-  use std::fmt::{Display, Debug};\n+  use std::fmt::{Debug, Display};\n+  use std::io::{Read, Write};\n\n@@ -48:57, +48:54 @@\n-              T::Sum(Tag { tag, val }) \u003d\u003e U::Sum(\n-                  Tag { tag: tag.as_str(), val: Box::new(val.to_u()) }\n-              ),\n-              T::Record(map) \u003d\u003e U::Record(\n-                  map.iter().map(|(k, v)| (k.as_str(), v.to_u())).collect()\n-              ),\n-              T::List(l) \u003d\u003e U::List(\n-                  l.iter().map(|v| v.to_u()).collect::\u003cVec\u003cU\u003c\u0027a\u003e\u003e\u003e()\n-              ),\n+              T::Sum(Tag { tag, val }) \u003d\u003e U::Sum(Tag {\n+                  tag: tag.as_str(),\n+                  val: Box::new(val.to_u()),\n+              }),\n+              T::Record(map) \u003d\u003e U::Record(map.iter().map(|(k, v)| (k.as_str(), v.to_u())).collect()),\n+              T::List(l) \u003d\u003e U::List(l.iter().map(|v| v.to_u()).collect::\u003cVec\u003cU\u003c\u0027a\u003e\u003e\u003e()),\n\n@@ -63:64, +60:61 @@\n-              o \u003d\u003e o.to_u().encode()\n+              o \u003d\u003e o.to_u().encode(),\n\n@@ -112:115, +109:113 @@\n-              U::Sum(Tag { tag, val }) \u003d\u003e T::Sum(\n-                  Tag { tag: (*tag).to_owned(), val: Box::new(val.to_t()) }\n-              ),\n+              U::Sum(Tag { tag, val }) \u003d\u003e T::Sum(Tag {\n+                  tag: (*tag).to_owned(),\n+                  val: Box::new(val.to_t()),\n+              }),\n\n@@ -116:117, +114:117 @@\n-                  map.iter().map(|(k, v)| ((*k).to_owned(), v.to_t())).collect::\u003cHashMap\u003cString, T\u003e\u003e()\n+                  map.iter()\n+                      .map(|(k, v)| ((*k).to_owned(), v.to_t()))\n+                      .collect::\u003cHashMap\u003cString, T\u003e\u003e(),\n\n@@ -118:121, +118:119 @@\n-              U::List(l) \u003d\u003e T::List(\n-                  l.iter().map(|v| v.to_t()).collect::\u003cVec\u003cT\u003e\u003e()\n-              ),\n+              U::List(l) \u003d\u003e T::List(l.iter().map(|v| v.to_t()).collect::\u003cVec\u003cT\u003e\u003e()),\n\n@@ -129:130, +127:128 @@\n-      pub val: Box\u003cA\u003e\n+      pub val: Box\u003cA\u003e,\n\n@@ -134:139, +132:139 @@\n-          where F: Fn(A) -\u003e B {\n-            Tag {\n-                tag: self.tag,\n-                val: Box::new(f(*self.val))\n-            }\n+      where\n+          F: Fn(A) -\u003e B,\n+      {\n+          Tag {\n+              tag: self.tag,\n+              val: Box::new(f(*self.val)),\n+          }\n\n@@ -149:188, +149:194 @@\n-    match u {\n-        U::Unit \u003d\u003e write!(w, \"u,\"),\n-        U::N1(b) \u003d\u003e if *b { write!(w, \"n1:1,\") } else { write!(w, \"n1:0,\") },\n-        U::N3(n) \u003d\u003e write!(w, \"n3:{},\", n),\n-        U::N6(n) \u003d\u003e write!(w, \"n6:{},\", n),\n-        U::N7(n) \u003d\u003e write!(w, \"n7:{},\", n),\n-        U::I3(i) \u003d\u003e write!(w, \"i3:{},\", i),\n-        U::I6(i) \u003d\u003e write!(w, \"i6:{},\", i),\n-        U::I7(i) \u003d\u003e write!(w, \"i7:{},\", i),\n-        U::Text(s) \u003d\u003e {\n-            write!(w, \"t{}:\", s.len());\n-            w.write_all(s.as_bytes());\n-            write!(w, \",\")\n-        }\n-        U::Binary(s) \u003d\u003e {\n-            write!(w, \"b{}:\", s.len());\n-            w.write_all(\u0026s);\n-            write!(w, \",\")\n-        },\n-        U::Sum(Tag{tag, val}) \u003d\u003e encode_tag(w, tag, val),\n-        U::Record(m) \u003d\u003e {\n-            let mut c \u003d std::io::Cursor::new(vec![]);\n-            for (k, v) in m {\n-                encode_tag(\u0026mut c, k, v)?;\n-            }\n-            write!(w, \"{{{}:\", c.get_ref().len())?;\n-            w.write_all(c.get_ref())?;\n-            write!(w, \"}}\")\n-        },\n-        U::List(l) \u003d\u003e {\n-            let mut c \u003d std::io::Cursor::new(vec![]);\n-            for u in l {\n-                encode(\u0026mut c, u)?;\n-            }\n-            write!(w, \"[{}:\", c.get_ref().len())?;\n-            w.write_all(c.get_ref())?;\n-            write!(w, \"]\")\n-        }\n-    }\n+      match u {\n+          U::Unit \u003d\u003e write!(w, \"u,\"),\n+          U::N1(b) \u003d\u003e {\n+              if *b {\n+                  write!(w, \"n1:1,\")\n+              } else {\n+                  write!(w, \"n1:0,\")\n+              }\n+          }\n+          U::N3(n) \u003d\u003e write!(w, \"n3:{},\", n),\n+          U::N6(n) \u003d\u003e write!(w, \"n6:{},\", n),\n+          U::N7(n) \u003d\u003e write!(w, \"n7:{},\", n),\n+          U::I3(i) \u003d\u003e write!(w, \"i3:{},\", i),\n+          U::I6(i) \u003d\u003e write!(w, \"i6:{},\", i),\n+          U::I7(i) \u003d\u003e write!(w, \"i7:{},\", i),\n+          U::Text(s) \u003d\u003e {\n+              write!(w, \"t{}:\", s.len());\n+              w.write_all(s.as_bytes());\n+              write!(w, \",\")\n+          }\n+          U::Binary(s) \u003d\u003e {\n+              write!(w, \"b{}:\", s.len());\n+              w.write_all(\u0026s);\n+              write!(w, \",\")\n+          }\n+          U::Sum(Tag { tag, val }) \u003d\u003e encode_tag(w, tag, val),\n+          U::Record(m) \u003d\u003e {\n+              let mut c \u003d std::io::Cursor::new(vec![]);\n+              for (k, v) in m {\n+                  encode_tag(\u0026mut c, k, v)?;\n+              }\n+              write!(w, \"{{{}:\", c.get_ref().len())?;\n+              w.write_all(c.get_ref())?;\n+              write!(w, \"}}\")\n+          }\n+          U::List(l) \u003d\u003e {\n+              let mut c \u003d std::io::Cursor::new(vec![]);\n+              for u in l {\n+                  encode(\u0026mut c, u)?;\n+              }\n+              write!(w, \"[{}:\", c.get_ref().len())?;\n+              w.write_all(c.get_ref())?;\n+              write!(w, \"]\")\n+          }\n+      }\n\n@@ -199:200, +205:212 @@\n-              _ \u003d\u003e exec_helpers::die_user_error(prog_name, format!(\"stdin contained some soup after netencode value: {:?}\", String::from_utf8_lossy(rest)))\n+              _ \u003d\u003e exec_helpers::die_user_error(\n+                  prog_name,\n+                  format!(\n+                      \"stdin contained some soup after netencode value: {:?}\",\n+                      String::from_utf8_lossy(rest)\n+                  ),\n+              ),\n\n@@ -201:202, +213:217 @@\n-          Err(err) \u003d\u003e exec_helpers::die_user_error(prog_name, format!(\"unable to parse netencode from stdin: {:?}\", err))\n+          Err(err) \u003d\u003e exec_helpers::die_user_error(\n+              prog_name,\n+              format!(\"unable to parse netencode from stdin: {:?}\", err),\n+          ),\n\n@@ -207:208, +222:223 @@\n-      use super::{T, Tag, U};\n+      use super::{Tag, T, U};\n\n@@ -209:211 @@\n-      use std::str::FromStr;\n-      use std::ops::Neg;\n\n@@ +225:227 @@\n+      use std::ops::Neg;\n+      use std::str::FromStr;\n\n@@ -213:215, +228:229 @@\n-      use nom::{IResult};\n-      use nom::branch::{alt};\n+      use nom::branch::alt;\n\n@@ -216:219, +230:232 @@\n-      use nom::character::streaming::{digit1, char};\n-      use nom::sequence::{tuple};\n-      use nom::combinator::{map, map_res, flat_map, map_parser, opt};\n+      use nom::character::streaming::{char, digit1};\n+      use nom::combinator::{flat_map, map, map_parser, map_res, opt};\n\n@@ +233:235 @@\n+      use nom::sequence::tuple;\n+      use nom::IResult;\n\n@@ -229:232, +244:247 @@\n-              map_res(\n-                  map_res(digit1, |n| std::str::from_utf8(n)),\n-                  |s| s.parse::\u003cusize\u003e())\n+              map_res(map_res(digit1, |n| std::str::from_utf8(n)), |s| {\n+                  s.parse::\u003cusize\u003e()\n+              }),\n\n@@ -240:248, +255:257 @@\n-              let (s, (len, _)) \u003d tuple((\n-                  usize_t,\n-                  char(\u0027:\u0027)\n-              ))(s)?;\n-              let (s, (res, _)) \u003d tuple((\n-                  take(len),\n-                  char(end)\n-              ))(s)?;\n+              let (s, (len, _)) \u003d tuple((usize_t, char(\u0027:\u0027)))(s)?;\n+              let (s, (res, _)) \u003d tuple((take(len), char(end)))(s)?;\n\n@@ -252:253 @@\n-  \n\n@@ -258:263, +266:270 @@\n-                  map_res(\n-                      map_res(digit1, |n: \u0026[u8]| std::str::from_utf8(n)),\n-                      |s| s.parse::\u003cI\u003e()\n-                  ),\n-                  char(\u0027,\u0027)\n+                  map_res(map_res(digit1, |n: \u0026[u8]| std::str::from_utf8(n)), |s| {\n+                      s.parse::\u003cI\u003e()\n+                  }),\n+                  char(\u0027,\u0027),\n\n@@ -269:273, +276:280 @@\n-          context(\"bool\", alt((\n-              map(tag(\"n1:0,\"), |_| false),\n-              map(tag(\"n1:1,\"), |_| true),\n-          )))\n+          context(\n+              \"bool\",\n+              alt((map(tag(\"n1:0,\"), |_| false), map(tag(\"n1:1,\"), |_| true))),\n+          )\n\n@@ -275:296, +282:301 @@\n-      fn int_t\u003c\u0027a, I: FromStr + Neg\u003cOutput\u003dI\u003e\u003e(t: \u0026\u0027static str) -\u003e impl Fn(\u0026\u0027a [u8]) -\u003e IResult\u003c\u0026[u8], I\u003e {\n-          context(\n-              t,\n-              move |s: \u0026\u0027a [u8]| {\n-                  let (s, (_, _, neg, int, _)) \u003d tuple((\n-                      tag(t.as_bytes()),\n-                      char(\u0027:\u0027),\n-                      opt(char(\u0027-\u0027)),\n-                      map_res(\n-                          map_res(digit1, |n: \u0026[u8]| std::str::from_utf8(n)),\n-                          |s| s.parse::\u003cI\u003e()\n-                      ),\n-                      char(\u0027,\u0027)\n-                  ))(s)?;\n-                  let res \u003d match neg {\n-                      Some(_) \u003d\u003e -int,\n-                      None \u003d\u003e int,\n-                  };\n-                  Ok((s, res))\n-              }\n-          )\n+      fn int_t\u003c\u0027a, I: FromStr + Neg\u003cOutput \u003d I\u003e\u003e(\n+          t: \u0026\u0027static str,\n+      ) -\u003e impl Fn(\u0026\u0027a [u8]) -\u003e IResult\u003c\u0026[u8], I\u003e {\n+          context(t, move |s: \u0026\u0027a [u8]| {\n+              let (s, (_, _, neg, int, _)) \u003d tuple((\n+                  tag(t.as_bytes()),\n+                  char(\u0027:\u0027),\n+                  opt(char(\u0027-\u0027)),\n+                  map_res(map_res(digit1, |n: \u0026[u8]| std::str::from_utf8(n)), |s| {\n+                      s.parse::\u003cI\u003e()\n+                  }),\n+                  char(\u0027,\u0027),\n+              ))(s)?;\n+              let res \u003d match neg {\n+                  Some(_) \u003d\u003e -int,\n+                  None \u003d\u003e int,\n+              };\n+              Ok((s, res))\n+          })\n\n@@ -300:306, +305:309 @@\n-          map(tag_g(t_t),\n-              |Tag {tag, val}|\n-              Tag {\n-                  tag: tag.to_string(),\n-                  val\n-              })(s)\n+          map(tag_g(t_t), |Tag { tag, val }| Tag {\n+              tag: tag.to_string(),\n+              val,\n+          })(s)\n\n@@ -310:311, +313:314 @@\n-          P: Fn(\u0026\u0027a [u8]) -\u003e IResult\u003c\u0026\u0027a [u8], O\u003e\n+          P: Fn(\u0026\u0027a [u8]) -\u003e IResult\u003c\u0026\u0027a [u8], O\u003e,\n\n@@ -315:321, +318:326 @@\n-              Ok((s, Tag {\n-                  tag: std::str::from_utf8(tag)\n-                      .map_err(|_| nom::Err::Failure((s, ErrorKind::Char)))?,\n-                  val: Box::new(val)\n-              }))\n-  \n+              Ok((\n+                  s,\n+                  Tag {\n+                      tag: std::str::from_utf8(tag)\n+                          .map_err(|_| nom::Err::Failure((s, ErrorKind::Char)))?,\n+                      val: Box::new(val),\n+                  },\n+              ))\n\n@@ -332:335, +337:340 @@\n-          Ok((s,\n-              std::str::from_utf8(res)\n-                  .map_err(|_| nom::Err::Failure((s, ErrorKind::Char)))?,\n+          Ok((\n+              s,\n+              std::str::from_utf8(res).map_err(|_| nom::Err::Failure((s, ErrorKind::Char)))?,\n\n@@ -376:377, +381:382 @@\n-              nom::multi::many0(inner_no_empty_string(inner))\n+              nom::multi::many0(inner_no_empty_string(inner)),\n\n@@ -382:383, +387:389 @@\n-          Ok((s,\n+          Ok((\n+              s,\n\n@@ -384:386, +390:393 @@\n-              .map(|(k, v)| (k.to_string(), v))\n-              .collect::\u003cHashMap\u003c_,_\u003e\u003e()))\n+                  .map(|(k, v)| (k.to_string(), v))\n+                  .collect::\u003cHashMap\u003c_, _\u003e\u003e(),\n+          ))\n\n@@ -391:392, +398:399 @@\n-          P: Fn(\u0026\u0027a [u8]) -\u003e IResult\u003c\u0026\u0027a [u8], O\u003e\n+          P: Fn(\u0026\u0027a [u8]) -\u003e IResult\u003c\u0026\u0027a [u8], O\u003e,\n\n@@ -399:400, +406:407 @@\n-                      |mut acc: HashMap\u003c_,_\u003e, Tag { tag, mut val }| {\n+                      |mut acc: HashMap\u003c_, _\u003e, Tag { tag, mut val }| {\n\n@@ -404:406, +411:413 @@\n-                      }\n-                  )\n+                      },\n+                  ),\n\n@@ -409:410, +416:417 @@\n-                  Err(nom::Err::Failure((s,nom::error::ErrorKind::Many1)))\n+                  Err(nom::Err::Failure((s, nom::error::ErrorKind::Many1)))\n\n@@ -424:425 @@\n-  \n\n@@ -432:433 @@\n-  \n\n@@ -445:446, +450:451 @@\n-      pub fn t_t(s: \u0026[u8]) -\u003e IResult\u003c\u0026[u8], T\u003e  {\n+      pub fn t_t(s: \u0026[u8]) -\u003e IResult\u003c\u0026[u8], T\u003e {\n\n@@ -453:454 @@\n-  \n\n@@ -462:463 @@\n-  \n\n@@ -481:485, +484:485 @@\n-              assert_eq!(\n-                  unit_t(\"u,\".as_bytes()),\n-                  Ok((\"\".as_bytes(), ()))\n-              );\n+              assert_eq!(unit_t(\"u,\".as_bytes()), Ok((\"\".as_bytes(), ())));\n\n@@ -489:497, +489:491 @@\n-              assert_eq!(\n-                  bool_t()(\"n1:0,\".as_bytes()),\n-                  Ok((\"\".as_bytes(), false))\n-              );\n-              assert_eq!(\n-                  bool_t()(\"n1:1,\".as_bytes()),\n-                  Ok((\"\".as_bytes(), true))\n-              );\n+              assert_eq!(bool_t()(\"n1:0,\".as_bytes()), Ok((\"\".as_bytes(), false)));\n+              assert_eq!(bool_t()(\"n1:1,\".as_bytes()), Ok((\"\".as_bytes(), true)));\n\n@@ -501:505, +495:496 @@\n-              assert_eq!(\n-                  usize_t(\"32foo\".as_bytes()),\n-                  Ok((\"foo\".as_bytes(), 32))\n-              );\n+              assert_eq!(usize_t(\"32foo\".as_bytes()), Ok((\"foo\".as_bytes(), 32)));\n\n@@ -515:516, +506:510 @@\n-                  Err(nom::Err::Error((\"1024,abc\".as_bytes(), nom::error::ErrorKind::MapRes)))\n+                  Err(nom::Err::Error((\n+                      \"1024,abc\".as_bytes(),\n+                      nom::error::ErrorKind::MapRes\n+                  )))\n\n@@ -544:545, +538:540 @@\n-                  \"{}\", r\"t5:hello,\"\n+                  \"{}\",\n+                  r\"t5:hello,\"\n\n@@ -550:551, +545:547 @@\n-                  \"{}\", r\"t4:fo,\"\n+                  \"{}\",\n+                  r\"t4:fo,\"\n\n@@ -555:556, +551:553 @@\n-                  \"{}\", r\"t9:今日は,\"\n+                  \"{}\",\n+                  r\"t9:今日は,\"\n\n@@ -564:565, +561:563 @@\n-                  \"{}\", r\"b5:hello,\"\n+                  \"{}\",\n+                  r\"b5:hello,\"\n\n@@ -570:571, +568:570 @@\n-                  \"{}\", r\"b4:fo,\"\n+                  \"{}\",\n+                  r\"b4:fo,\"\n\n@@ -576:578, +575:578 @@\n-                      \"{}\", r\"b4:fo,\"\n-                  );\n+                  \"{}\",\n+                  r\"b4:fo,\"\n+              );\n\n@@ -581:582, +581:583 @@\n-                  \"{}\", r\"b9:今日は,\"\n+                  \"{}\",\n+                  r\"b9:今日は,\"\n\n@@ -590:591, +591:593 @@\n-                  \"{}\", r\"[0:]\"\n+                  \"{}\",\n+                  r\"[0:]\"\n\n@@ -594:600, +596:599 @@\n-                  Ok((\"\".as_bytes(), vec![\n-                      T::Unit,\n-                      T::Unit,\n-                      T::Unit,\n-                  ])),\n-                  \"{}\", r\"[6:u,u,u,]\"\n+                  Ok((\"\".as_bytes(), vec![T::Unit, T::Unit, T::Unit,])),\n+                  \"{}\",\n+                  r\"[6:u,u,u,]\"\n\n@@ -603:609, +602:608 @@\n-                  Ok((\"\".as_bytes(), vec![\n-                      T::Unit,\n-                      T::List(vec![T::Text(\"foo\".to_owned())]),\n-                      T::Unit,\n-                  ])),\n-                  \"{}\", r\"[15:u,[7:t3:foo,]u,]\"\n+                  Ok((\n+                      \"\".as_bytes(),\n+                      vec![T::Unit, T::List(vec![T::Text(\"foo\".to_owned())]), T::Unit,]\n+                  )),\n+                  \"{}\",\n+                  r\"[15:u,[7:t3:foo,]u,]\"\n\n@@ -616:622, +615:627 @@\n-                  Ok((\"\".as_bytes(), vec![\n-                      (\"a\".to_owned(), T::Unit),\n-                      (\"b\".to_owned(), T::Unit),\n-                      (\"c\".to_owned(), T::Unit),\n-                  ].into_iter().collect::\u003cHashMap\u003cString, T\u003e\u003e())),\n-                  \"{}\", r\"{21:\u003c1:a|u,\u003c1:b|u,\u003c1:c|u,}\"\n+                  Ok((\n+                      \"\".as_bytes(),\n+                      vec![\n+                          (\"a\".to_owned(), T::Unit),\n+                          (\"b\".to_owned(), T::Unit),\n+                          (\"c\".to_owned(), T::Unit),\n+                      ]\n+                      .into_iter()\n+                      .collect::\u003cHashMap\u003cString, T\u003e\u003e()\n+                  )),\n+                  \"{}\",\n+                  r\"{21:\u003c1:a|u,\u003c1:b|u,\u003c1:c|u,}\"\n\n@@ -626:631, +631:639 @@\n-                  Ok((\"\".as_bytes(), vec![\n-                      (\"a\".to_owned(), T::I3(-1)),\n-                      (\"b\".to_owned(), T::Unit),\n-                  ].into_iter().collect::\u003cHashMap\u003c_,_\u003e\u003e())),\n-                  \"{}\", r\"{25:\u003c1:a|u,\u003c1:b|u,\u003c1:a|i1:-1,}\"\n+                  Ok((\n+                      \"\".as_bytes(),\n+                      vec![(\"a\".to_owned(), T::I3(-1)), (\"b\".to_owned(), T::Unit),]\n+                          .into_iter()\n+                          .collect::\u003cHashMap\u003c_, _\u003e\u003e()\n+                  )),\n+                  \"{}\",\n+                  r\"{25:\u003c1:a|u,\u003c1:b|u,\u003c1:a|i1:-1,}\"\n\n@@ -635:637, +643:649 @@\n-                  Err(nom::Err::Failure((\"\".as_bytes(), nom::error::ErrorKind::Many1))),\n-                  \"{}\", r\"{0:}\"\n+                  Err(nom::Err::Failure((\n+                      \"\".as_bytes(),\n+                      nom::error::ErrorKind::Many1\n+                  ))),\n+                  \"{}\",\n+                  r\"{0:}\"\n\n@@ -645:646, +657:659 @@\n-                  \"{}\", r\"n3:255,\"\n+                  \"{}\",\n+                  r\"n3:255,\"\n\n@@ -650:651, +663:665 @@\n-                  \"{}\", r\"t6:halloo,\"\n+                  \"{}\",\n+                  r\"t6:halloo,\"\n\n@@ -654:659, +668:677 @@\n-                  Ok((\"\".as_bytes(), T::Sum (Tag {\n-                      tag: \"foo\".to_owned(),\n-                      val: Box::new(T::Text(\"halloo\".to_owned()))\n-                  }))),\n-                  \"{}\", r\"\u003c3:foo|t6:halloo,\"\n+                  Ok((\n+                      \"\".as_bytes(),\n+                      T::Sum(Tag {\n+                          tag: \"foo\".to_owned(),\n+                          val: Box::new(T::Text(\"halloo\".to_owned()))\n+                      })\n+                  )),\n+                  \"{}\",\n+                  r\"\u003c3:foo|t6:halloo,\"\n\n@@ -664:673, +682:711 @@\n-                  Ok((\"\".as_bytes(), T::Record(vec![\n-                      (\"a\".to_owned(), T::Unit),\n-                      (\"foo\".to_owned(), T::List(vec![\n-                          T::Sum(Tag { tag: \"A\".to_owned(), val: Box::new(T::Unit) }),\n-                          T::Sum(Tag { tag: \"A\".to_owned(), val: Box::new(T::N1(true)) }),\n-                          T::Sum(Tag { tag: \"B\".to_owned(), val: Box::new(T::List(vec![T::I3(127)])) }),\n-                      ]))\n-                  ].into_iter().collect::\u003cHashMap\u003cString, T\u003e\u003e()))),\n-                  \"{}\", r\"{52:\u003c1:a|u,\u003c3:foo|[33:\u003c1:A|u,\u003c1:A|n1:1,\u003c1:B|[7:i3:127,]]}\"\n+                  Ok((\n+                      \"\".as_bytes(),\n+                      T::Record(\n+                          vec![\n+                              (\"a\".to_owned(), T::Unit),\n+                              (\n+                                  \"foo\".to_owned(),\n+                                  T::List(vec![\n+                                      T::Sum(Tag {\n+                                          tag: \"A\".to_owned(),\n+                                          val: Box::new(T::Unit)\n+                                      }),\n+                                      T::Sum(Tag {\n+                                          tag: \"A\".to_owned(),\n+                                          val: Box::new(T::N1(true))\n+                                      }),\n+                                      T::Sum(Tag {\n+                                          tag: \"B\".to_owned(),\n+                                          val: Box::new(T::List(vec![T::I3(127)]))\n+                                      }),\n+                                  ])\n+                              )\n+                          ]\n+                          .into_iter()\n+                          .collect::\u003cHashMap\u003cString, T\u003e\u003e()\n+                      )\n+                  )),\n+                  \"{}\",\n+                  r\"{52:\u003c1:a|u,\u003c3:foo|[33:\u003c1:A|u,\u003c1:A|n1:1,\u003c1:B|[7:i3:127,]]}\"\n\n@@ -675:676 @@\n-  \n\n@@ -735:736, +772:776 @@\n-                  other \u003d\u003e Err(DecodeError(format!(\"Cannot decode {:?} into Binary\", other))),\n+                  other \u003d\u003e Err(DecodeError(format!(\n+                      \"Cannot decode {:?} into Binary\",\n+                      other\n+                  ))),\n\n@@ -766:767, +806:808 @@\n-          where Inner: Decoder\u003c\u0027a\u003e\n+      where\n+          Inner: Decoder\u003c\u0027a\u003e,\n\n@@ -771:773, +812:814 @@\n-                  U::Record(map) \u003d\u003e\n-                      map.into_iter()\n+                  U::Record(map) \u003d\u003e map\n+                      .into_iter()\n\n@@ -775:776, +816:817 @@\n-                  o \u003d\u003e Err(DecodeError(format!(\"Cannot decode {:?} into record\", o)))\n+                  o \u003d\u003e Err(DecodeError(format!(\"Cannot decode {:?} into record\", o))),\n\n@@ -784:785, +825:826 @@\n-          pub inner: T\n+          pub inner: T,\n\n@@ -787:789, +828:831 @@\n-      impl \u003c\u0027a, Inner\u003e Decoder\u003c\u0027a\u003e for RecordDot\u003c\u0027_, Inner\u003e\n-          where Inner: Decoder\u003c\u0027a\u003e + Clone\n+      impl\u003c\u0027a, Inner\u003e Decoder\u003c\u0027a\u003e for RecordDot\u003c\u0027_, Inner\u003e\n+      where\n+          Inner: Decoder\u003c\u0027a\u003e + Clone,\n\n@@ -795:796, +837:841 @@\n-                      None \u003d\u003e Err(DecodeError(format!(\"Cannot find `{}` in record map\", self.field))),\n+                      None \u003d\u003e Err(DecodeError(format!(\n+                          \"Cannot find `{}` in record map\",\n+                          self.field\n+                      ))),\n\n@@ -804:805, +849:850 @@\n-      pub struct OneOf\u003cT, A\u003e{\n+      pub struct OneOf\u003cT, A\u003e {\n\n@@ -809:812, +854:858 @@\n-      impl \u003c\u0027a, Inner\u003e Decoder\u003c\u0027a\u003e for OneOf\u003cInner, Inner::A\u003e\n-          where Inner: Decoder\u003c\u0027a\u003e,\n-                Inner::A: Display + Debug + PartialEq\n+      impl\u003c\u0027a, Inner\u003e Decoder\u003c\u0027a\u003e for OneOf\u003cInner, Inner::A\u003e\n+      where\n+          Inner: Decoder\u003c\u0027a\u003e,\n+          Inner::A: Display + Debug + PartialEq,\n\n@@ -818:819, +864:868 @@\n-                      false \u003d\u003e Err(DecodeError(format!(\"{} is not one of {:?}\", inner, self.list)))\n+                      false \u003d\u003e Err(DecodeError(format!(\n+                          \"{} is not one of {:?}\",\n+                          inner, self.list\n+                      ))),\n\n@@ -820:821, +869:870 @@\n-                  Err(err) \u003d\u003e Err(err)\n+                  Err(err) \u003d\u003e Err(err),\n\n@@ -829:831, +878:881 @@\n-      impl \u003c\u0027a, Inner\u003e Decoder\u003c\u0027a\u003e for Try\u003cInner\u003e\n-          where Inner: Decoder\u003c\u0027a\u003e\n+      impl\u003c\u0027a, Inner\u003e Decoder\u003c\u0027a\u003e for Try\u003cInner\u003e\n+      where\n+          Inner: Decoder\u003c\u0027a\u003e,\n\n@@ -836:837, +886:887 @@\n-                  Err(err) \u003d\u003e Ok(None)\n+                  Err(err) \u003d\u003e Ok(None),\n\n@@ -840:841 @@\n-  \n\n```\n","accounts_in_message":[],"_revision_number":3}],"current_revision_number":3,"current_revision":"ed68ba675191bc3da57019b14609deb713247821","revisions":{"be8e4e523b9448fe642d9738ab4efe84a9e5f328":{"kind":"REWORK","_number":1,"created":"2022-01-29 12:00:57.000000000","uploader":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"ref":"refs/changes/08/5108/1","fetch":{"anonymous http":{"url":"https://cl.tvl.fyi/depot","ref":"refs/changes/08/5108/1","commands":{"Checkout":"git fetch https://cl.tvl.fyi/depot refs/changes/08/5108/1 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://cl.tvl.fyi/depot refs/changes/08/5108/1 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://cl.tvl.fyi/depot refs/changes/08/5108/1 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://cl.tvl.fyi/depot refs/changes/08/5108/1"}}},"commit":{"parents":[{"commit":"d7b2637f59ac7ce0d1bcd099930c9d37dc0ee057","subject":"chore(nix/buildkite): reduce chunk size to 192","web_links":[{"name":"cgit","tooltip":"Open in GitWeb","url":"https://code.tvl.fyi/commit/?id\u003dd7b2637f59ac7ce0d1bcd099930c9d37dc0ee057"}]}],"author":{"name":"Profpatsch","email":"mail@profpatsch.de","date":"2022-01-29 11:50:19.000000000","tz":60},"committer":{"name":"Profpatsch","email":"mail@profpatsch.de","date":"2022-01-29 12:00:24.000000000","tz":60},"subject":"feat(users/Profpatsch/netencode): ignore earlier record entries","message":"feat(users/Profpatsch/netencode): ignore earlier record entries\n\nIt turns out that the netencode spec requiring to ignore *later*\nentries meant that every parser has to do an extra check for each\nelement, instead of just overriding the key in the hash map.\n\nThis leads to a situation where the simple implementation is the wrong\none, which would lead to very subtle problems in parsers (see also the\ninfamous “json duplicate record entry” problem which has been used for\nvarious exploits in the past).\n\nTo be fair, exploits are still possible, but at least a `Map.fromList`\nwill be the right implementation (provided it folds from the left) now\ninstead of the wrong one.\n\nExamples of the trivial implementation being now right:\n\nPython:\n\n    \u003e dict([(\"foo\", 1), (\"foo\", 2)])\n    {\u0027foo\u0027: 2}\n\nRust:\n\n    \u003e println!(\"{:?}\", HashMap::from([\n      (\"foo\", 1),\n      (\"foo\", 2)\n    ]));\n    {\"foo\": 2}\n\nHaskell:\n\n    \u003e Data.Map.fromList [ (\"foo\", 1), (\"foo\", 2) ]\n    fromList [(\"foo\",2)]\n\nChange-Id: Ife9593956f4718e5e720f4f348c227e4f3a71e2d\n","web_links":[{"name":"cgit","tooltip":"Open in GitWeb","url":"https://code.tvl.fyi/commit/?id\u003dbe8e4e523b9448fe642d9738ab4efe84a9e5f328"}],"resolve_conflicts_web_links":[{"name":"cgit","tooltip":"Open in GitWeb","url":"https://code.tvl.fyi/commit/?id\u003dbe8e4e523b9448fe642d9738ab4efe84a9e5f328"}]},"parents_data":[{"branch_name":"refs/heads/canon","commit_id":"d7b2637f59ac7ce0d1bcd099930c9d37dc0ee057","is_merged_in_target_branch":true,"change_id":"I6bf0e9e4ab0d5b8de22773e6cd5da8d0959cc448","change_number":5105,"patch_set_number":3,"change_status":"MERGED"}],"branch":"refs/heads/canon"},"471cabc92a4e973062f386e1141e9fb82c4e122e":{"kind":"REWORK","_number":2,"created":"2022-02-14 14:09:54.000000000","uploader":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"ref":"refs/changes/08/5108/2","fetch":{"anonymous http":{"url":"https://cl.tvl.fyi/depot","ref":"refs/changes/08/5108/2","commands":{"Checkout":"git fetch https://cl.tvl.fyi/depot refs/changes/08/5108/2 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://cl.tvl.fyi/depot refs/changes/08/5108/2 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://cl.tvl.fyi/depot refs/changes/08/5108/2 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://cl.tvl.fyi/depot refs/changes/08/5108/2"}}},"commit":{"parents":[{"commit":"82ba42c4396c35e8bf69535af311e9b9f0cffa17","subject":"feat(tvl-kit): add magrathea to TVL kit","web_links":[{"name":"cgit","tooltip":"Open in GitWeb","url":"https://code.tvl.fyi/commit/?id\u003d82ba42c4396c35e8bf69535af311e9b9f0cffa17"}]}],"author":{"name":"Profpatsch","email":"mail@profpatsch.de","date":"2022-01-29 11:50:19.000000000","tz":60},"committer":{"name":"Profpatsch","email":"mail@profpatsch.de","date":"2022-02-14 14:07:26.000000000","tz":60},"subject":"feat(users/Profpatsch/netencode): ignore earlier record entries","message":"feat(users/Profpatsch/netencode): ignore earlier record entries\n\nIt turns out that the netencode spec requiring to ignore *later*\nentries meant that every parser has to do an extra check for each\nelement, instead of just overriding the key in the hash map.\n\nThis leads to a situation where the simple implementation is the wrong\none, which would lead to very subtle problems in parsers (see also the\ninfamous “json duplicate record entry” problem which has been used for\nvarious exploits in the past).\n\nTo be fair, exploits are still possible, but at least a `Map.fromList`\nwill be the right implementation (provided it folds from the left) now\ninstead of the wrong one.\n\nExamples of the trivial implementation being now right:\n\nPython:\n\n    \u003e dict([(\"foo\", 1), (\"foo\", 2)])\n    {\u0027foo\u0027: 2}\n\nRust:\n\n    \u003e println!(\"{:?}\", HashMap::from([\n      (\"foo\", 1),\n      (\"foo\", 2)\n    ]));\n    {\"foo\": 2}\n\nHaskell:\n\n    \u003e Data.Map.fromList [ (\"foo\", 1), (\"foo\", 2) ]\n    fromList [(\"foo\",2)]\n\nChange-Id: Ife9593956f4718e5e720f4f348c227e4f3a71e2d\n","web_links":[{"name":"cgit","tooltip":"Open in GitWeb","url":"https://code.tvl.fyi/commit/?id\u003d471cabc92a4e973062f386e1141e9fb82c4e122e"}],"resolve_conflicts_web_links":[{"name":"cgit","tooltip":"Open in GitWeb","url":"https://code.tvl.fyi/commit/?id\u003d471cabc92a4e973062f386e1141e9fb82c4e122e"}]},"parents_data":[{"branch_name":"refs/heads/canon","commit_id":"82ba42c4396c35e8bf69535af311e9b9f0cffa17","is_merged_in_target_branch":true,"change_id":"I182259a7ddb61b4ebdce98ef7893a0ac58a6baec","change_number":5271,"patch_set_number":6,"change_status":"MERGED"}],"branch":"refs/heads/canon"},"ed68ba675191bc3da57019b14609deb713247821":{"kind":"NO_CODE_CHANGE","_number":3,"created":"2022-02-14 14:12:19.000000000","uploader":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"},"ref":"refs/changes/08/5108/3","fetch":{"anonymous http":{"url":"https://cl.tvl.fyi/depot","ref":"refs/changes/08/5108/3","commands":{"Checkout":"git fetch https://cl.tvl.fyi/depot refs/changes/08/5108/3 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://cl.tvl.fyi/depot refs/changes/08/5108/3 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://cl.tvl.fyi/depot refs/changes/08/5108/3 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://cl.tvl.fyi/depot refs/changes/08/5108/3"}}},"commit":{"parents":[{"commit":"82ba42c4396c35e8bf69535af311e9b9f0cffa17","subject":"feat(tvl-kit): add magrathea to TVL kit","web_links":[{"name":"cgit","tooltip":"Open in GitWeb","url":"https://code.tvl.fyi/commit/?id\u003d82ba42c4396c35e8bf69535af311e9b9f0cffa17"}]}],"author":{"name":"Profpatsch","email":"mail@profpatsch.de","date":"2022-01-29 11:50:19.000000000","tz":60},"committer":{"name":"Profpatsch","email":"mail@profpatsch.de","date":"2022-02-14 14:12:19.000000000","tz":0},"subject":"feat(users/Profpatsch/netencode): ignore earlier record entries","message":"feat(users/Profpatsch/netencode): ignore earlier record entries\n\nIt turns out that the netencode spec requiring to ignore *later*\nentries meant that every parser has to do an extra check for each\nelement, instead of just overriding the key in the hash map.\n\nThis leads to a situation where the simple implementation is the wrong\none, which would lead to very subtle problems in parsers (see also the\ninfamous “json duplicate record entry” problem which has been used for\nvarious exploits in the past).\n\nTo be fair, exploits are still possible, but at least a `Map.fromList`\nwill be the right implementation (provided it folds from the left) now\ninstead of the wrong one.\n\nExamples of the trivial implementation being now right:\n\nPython:\n\n    \u003e dict([(\"foo\", 1), (\"foo\", 2)])\n    {\u0027foo\u0027: 2}\n\nRust:\n\n    \u003e println!(\"{:?}\", HashMap::from([\n      (\"foo\", 1),\n      (\"foo\", 2)\n    ]));\n    {\"foo\": 2}\n\nHaskell:\n\n    \u003e Data.Map.fromList [ (\"foo\", 1), (\"foo\", 2) ]\n    fromList [(\"foo\",2)]\n\nChange-Id: Ife9593956f4718e5e720f4f348c227e4f3a71e2d\nReviewed-on: https://cl.tvl.fyi/c/depot/+/5108\nTested-by: BuildkiteCI\nReviewed-by: Profpatsch \u003cmail@profpatsch.de\u003e\nReviewed-by: sterni \u003csternenseemann@systemli.org\u003e\nAutosubmit: Profpatsch \u003cmail@profpatsch.de\u003e\n","web_links":[{"name":"cgit","tooltip":"Open in GitWeb","url":"https://code.tvl.fyi/commit/?id\u003ded68ba675191bc3da57019b14609deb713247821"}],"resolve_conflicts_web_links":[{"name":"cgit","tooltip":"Open in GitWeb","url":"https://code.tvl.fyi/commit/?id\u003ded68ba675191bc3da57019b14609deb713247821"}]},"parents_data":[{"branch_name":"refs/heads/canon","commit_id":"82ba42c4396c35e8bf69535af311e9b9f0cffa17","is_merged_in_target_branch":true,"change_id":"I182259a7ddb61b4ebdce98ef7893a0ac58a6baec","change_number":5271,"patch_set_number":6,"change_status":"MERGED"}],"branch":"refs/heads/canon"}},"requirements":[],"submit_records":[{"status":"CLOSED","labels":[{"label":"Code-Review-from-owners","status":"OK","applied_by":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"}},{"label":"Autosubmit","status":"MAY"},{"label":"Conformant-Commit-Message","status":"OK","applied_by":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"}},{"label":"All-Comments-Resolved","status":"OK","applied_by":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"}},{"label":"Verified","status":"OK","applied_by":{"_account_id":1000014,"name":"BuildkiteCI","username":"buildkite","tags":["SERVICE_USER"]}},{"label":"Code-Review","status":"OK","applied_by":{"_account_id":1000013,"name":"Profpatsch","email":"mail@profpatsch.de","username":"Profpatsch"}}]}],"submit_requirements":[{"name":"Verified","status":"SATISFIED","is_legacy":true,"submittability_expression_result":{"expression":"label:Verified\u003dCustom-Rule","fulfilled":true,"status":"PASS","passing_atoms":["label:Verified\u003dCustom-Rule"],"failing_atoms":[]}},{"name":"All-Comments-Resolved","status":"SATISFIED","is_legacy":true,"submittability_expression_result":{"expression":"label:All-Comments-Resolved\u003dCustom-Rule","fulfilled":true,"status":"PASS","passing_atoms":["label:All-Comments-Resolved\u003dCustom-Rule"],"failing_atoms":[]}},{"name":"Code-Review-from-owners","status":"SATISFIED","is_legacy":true,"submittability_expression_result":{"expression":"label:Code-Review-from-owners\u003dCustom-Rule","fulfilled":true,"status":"PASS","passing_atoms":["label:Code-Review-from-owners\u003dCustom-Rule"],"failing_atoms":[]}},{"name":"Code-Review","status":"SATISFIED","is_legacy":true,"submittability_expression_result":{"expression":"label:Code-Review\u003dCustom-Rule","fulfilled":true,"status":"PASS","passing_atoms":["label:Code-Review\u003dCustom-Rule"],"failing_atoms":[]}},{"name":"Conformant-Commit-Message","status":"SATISFIED","is_legacy":true,"submittability_expression_result":{"expression":"label:Conformant-Commit-Message\u003dCustom-Rule","fulfilled":true,"status":"PASS","passing_atoms":["label:Conformant-Commit-Message\u003dCustom-Rule"],"failing_atoms":[]}}]}
