131 lines
3.8 KiB
Rust
131 lines
3.8 KiB
Rust
use super::{NarInfo, NarInfoBuilder};
|
|
use crate::{
|
|
error::{ParsingError, ParsingResult},
|
|
sig::Sig,
|
|
};
|
|
use alloc::{borrow::Cow, vec::Vec};
|
|
|
|
impl<'a> NarInfo<'a> {
|
|
/// Parses the contents of a narinfo file from str.
|
|
/// This function is also used to implement the [TryFrom] trait for &'a str.
|
|
///
|
|
/// For duplicate keys the last value is used(same behaviour as libstore).
|
|
/// Unknown keys return an error(unlike libstore where they're simply ignored).
|
|
///
|
|
/// ```
|
|
/// # fn http_get_str(_url: &str) -> &'static str { include_str!("../../sample.narinfo") }
|
|
/// use narinfo::NarInfo;
|
|
/// let data: &str =
|
|
/// http_get_str("https://cache.nixos.org/zn2h0kln2b02x4x6jqxymd4sg9cwvdsx.narinfo");
|
|
///
|
|
/// let parsed = NarInfo::parse(data).unwrap();
|
|
/// assert_eq!(parsed.store_path, "/nix/store/zzxrhj9056vjlanfjkinvhd7458yc2z8-liblouis-3.22.0");
|
|
/// ```
|
|
pub fn parse(value: &'a str) -> ParsingResult<Self> {
|
|
let mut builder = NarInfoBuilder::default();
|
|
let mut sigs = Vec::new();
|
|
|
|
for line in value.lines() {
|
|
let (key, value) = line
|
|
.split_once(':')
|
|
.map(|(k, v)| (k, v.trim()))
|
|
.ok_or(ParsingError::InvalidLine { line })?;
|
|
|
|
match key {
|
|
"StorePath" => builder.store_path(Cow::from(value)),
|
|
"URL" => builder.url(value),
|
|
"Compression" => builder.compression(Some(Cow::from(value))),
|
|
"FileHash" => builder.file_hash(Some(value)),
|
|
"NarHash" => builder.nar_hash(Cow::from(value)),
|
|
"NarSize" => {
|
|
let size: usize = ParsingError::try_parse_int(value, line)?;
|
|
builder.nar_size(size)
|
|
}
|
|
"FileSize" => {
|
|
let size: usize = ParsingError::try_parse_int(value, line)?;
|
|
builder.file_size(Some(size))
|
|
}
|
|
"Deriver" => builder.deriver(Some(Cow::from(value))),
|
|
"System" => builder.system(Some(Cow::from(value))),
|
|
"References" => builder.references(value.split(' ').map(Cow::from).collect()),
|
|
"Sig" => {
|
|
sigs.push(Sig::parse(value)?);
|
|
&mut builder
|
|
},
|
|
_ => return Err(ParsingError::UnknownKey { key }),
|
|
};
|
|
}
|
|
|
|
builder.sigs(sigs);
|
|
builder.build()
|
|
}
|
|
}
|
|
|
|
impl<'a> TryFrom<&'a str> for NarInfo<'a> {
|
|
type Error = crate::error::ParsingError<'a>;
|
|
|
|
fn try_from(value: &'a str) -> ParsingResult<Self> {
|
|
NarInfo::parse(value)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use alloc::borrow::Cow;
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn parses_sample_narinfo() {
|
|
let sample = include_str!("../../sample.narinfo");
|
|
let info = NarInfo::try_from(sample).unwrap();
|
|
assert_eq!(
|
|
info.store_path,
|
|
"/nix/store/zzxrhj9056vjlanfjkinvhd7458yc2z8-liblouis-3.22.0"
|
|
);
|
|
assert_eq!(
|
|
info.url,
|
|
"nar/0ccqg4il1m9qqh8b6x0x8nn7pjcphr82h2qdfc5gqq8dy7h2kp9x.nar.xz"
|
|
);
|
|
assert_eq!(info.compression, Some(Cow::Borrowed("xz")));
|
|
assert_eq!(
|
|
info.file_hash,
|
|
Some("sha256:0ccqg4il1m9qqh8b6x0x8nn7pjcphr82h2qdfc5gqq8dy7h2kp9x")
|
|
);
|
|
assert_eq!(info.file_size, Some(1914556));
|
|
assert_eq!(
|
|
info.nar_hash,
|
|
"sha256:0c8ld5yxcr6a6j63mvrqbqiy08q6f85wd74817ai7pvd5nkidcqw"
|
|
);
|
|
assert_eq!(info.nar_size, 11374872);
|
|
|
|
let expected_refs = [
|
|
"mhhlymrg2m70r8h94cwhv2d7a0c8l7g6-glibc-2.34-210",
|
|
"ppn8983d9b5r6k7mnhkbg6rqw7vgl1ij-libyaml-0.2.5",
|
|
"qm2lv1gpbyn0rsfai40cbvj3h4gz69yc-bash-5.1-p16",
|
|
"sn0w3f12547crckss4ybmnxmi29gpgq7-perl-5.34.1",
|
|
"zzxrhj9056vjlanfjkinvhd7458yc2z8-liblouis-3.22.0",
|
|
];
|
|
for (a, b) in info.references.iter().zip(expected_refs) {
|
|
assert_eq!(a, b);
|
|
}
|
|
|
|
assert_eq!(
|
|
info.deriver,
|
|
Some(Cow::Borrowed(
|
|
"dlxmsgfc0am35fh0kiy88zqr91x2dn5j-liblouis-3.22.0.drv"
|
|
))
|
|
);
|
|
|
|
let sig = &info.sigs[0];
|
|
assert_eq!(sig.key_name, "cache.nixos.org-1");
|
|
assert_eq!(sig.sig, "BJ5QGcOta2s76XC6sep9DbAv0x3TILh3hHSKyR+9rFWYuBDTWdHs1KHeUEpw2espE/zPPBp2yURO6/J4Dhf9DQ==");
|
|
|
|
let sig = &info.sigs[1];
|
|
assert_eq!(sig.key_name, "fake-test-sig-1");
|
|
assert_eq!(sig.sig, "BJ5QGcOta2s76XC6sep9DbAv0x3TILh3hHSKyR+9rFWYuBDTWdHs1KHeUEpw2espE/zPPBp2yURO6/J4Dhf9DQ==");
|
|
|
|
assert!(info.sigs.len() == 2);
|
|
}
|
|
}
|