fix(nix-compat/narinfo): don't allocate errors early

We also switch the MissingField error to &'static str, since we only 
parse a fixed set of fields.

Together, this makes the performance impact of error handling 
negligible in batch happy-path parsing.

Change-Id: I2bd0ef2f5b35fcaced56b32d238eca75ac199ef1
Reviewed-on: https://cl.tvl.fyi/c/depot/+/9867
Reviewed-by: flokli <flokli@flokli.de>
Autosubmit: edef <edef@edef.eu>
Tested-by: BuildkiteCI
This commit is contained in:
edef 2023-10-28 16:19:55 +00:00 committed by clbot
parent ae83998381
commit 12fb5004d9

View file

@ -80,11 +80,11 @@ impl<'a> NarInfo<'a> {
for line in input.lines() { for line in input.lines() {
let (tag, val) = line let (tag, val) = line
.split_once(':') .split_once(':')
.ok_or(Error::InvalidLine(line.to_string()))?; .ok_or_else(|| Error::InvalidLine(line.to_string()))?;
let val = val let val = val
.strip_prefix(' ') .strip_prefix(' ')
.ok_or(Error::InvalidLine(line.to_string()))?; .ok_or_else(|| Error::InvalidLine(line.to_string()))?;
match tag { match tag {
"StorePath" => { "StorePath" => {
@ -121,7 +121,7 @@ impl<'a> NarInfo<'a> {
"FileHash" => { "FileHash" => {
let val = val let val = val
.strip_prefix("sha256:") .strip_prefix("sha256:")
.ok_or(Error::MissingPrefixForHash(tag.to_string()))?; .ok_or_else(|| Error::MissingPrefixForHash(tag.to_string()))?;
let val = nixbase32::decode_fixed::<32>(val) let val = nixbase32::decode_fixed::<32>(val)
.map_err(|e| Error::UnableToDecodeHash(tag.to_string(), e))?; .map_err(|e| Error::UnableToDecodeHash(tag.to_string(), e))?;
@ -141,7 +141,7 @@ impl<'a> NarInfo<'a> {
"NarHash" => { "NarHash" => {
let val = val let val = val
.strip_prefix("sha256:") .strip_prefix("sha256:")
.ok_or(Error::MissingPrefixForHash(tag.to_string()))?; .ok_or_else(|| Error::MissingPrefixForHash(tag.to_string()))?;
let val = nixbase32::decode_fixed::<32>(val) let val = nixbase32::decode_fixed::<32>(val)
.map_err(|e| Error::UnableToDecodeHash(tag.to_string(), e))?; .map_err(|e| Error::UnableToDecodeHash(tag.to_string(), e))?;
@ -210,7 +210,8 @@ impl<'a> NarInfo<'a> {
signatures.push(val); signatures.push(val);
} }
"CA" => { "CA" => {
let val = parse_ca(val).ok_or(Error::UnableToParseCA(val.to_string()))?; let val =
parse_ca(val).ok_or_else(|| Error::UnableToParseCA(val.to_string()))?;
if ca.replace(val).is_some() { if ca.replace(val).is_some() {
return Err(Error::DuplicateField(tag.to_string())); return Err(Error::DuplicateField(tag.to_string()));
@ -223,15 +224,15 @@ impl<'a> NarInfo<'a> {
} }
Ok(NarInfo { Ok(NarInfo {
store_path: store_path.ok_or(Error::MissingField("StorePath".to_string()))?, store_path: store_path.ok_or(Error::MissingField("StorePath"))?,
nar_hash: nar_hash.ok_or(Error::MissingField("NarHash".to_string()))?, nar_hash: nar_hash.ok_or(Error::MissingField("NarHash"))?,
nar_size: nar_size.ok_or(Error::MissingField("NarSize".to_string()))?, nar_size: nar_size.ok_or(Error::MissingField("NarSize"))?,
references: references.ok_or(Error::MissingField("References".to_string()))?, references: references.ok_or(Error::MissingField("References"))?,
signatures, signatures,
ca, ca,
system, system,
deriver, deriver,
url: url.ok_or(Error::MissingField("URL".to_string()))?, url: url.ok_or(Error::MissingField("URL"))?,
compression, compression,
file_hash, file_hash,
file_size, file_size,
@ -417,7 +418,7 @@ pub enum Error {
DuplicateField(String), DuplicateField(String),
#[error("missing field: {0}")] #[error("missing field: {0}")]
MissingField(String), MissingField(&'static str),
#[error("invalid line: {0}")] #[error("invalid line: {0}")]
InvalidLine(String), InvalidLine(String),