diff options
Diffstat (limited to 'tvix/nix-compat/src/nar/listing/mod.rs')
-rw-r--r-- | tvix/nix-compat/src/nar/listing/mod.rs | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/tvix/nix-compat/src/nar/listing/mod.rs b/tvix/nix-compat/src/nar/listing/mod.rs new file mode 100644 index 000000000000..c1119a0199f4 --- /dev/null +++ b/tvix/nix-compat/src/nar/listing/mod.rs @@ -0,0 +1,65 @@ +//! Parser for the Nix archive listing format, aka .ls. +//! +//! LS files are produced by the C++ Nix implementation via `write-nar-listing=1` query parameter +//! passed to a store implementation when transferring store paths. +//! +//! Listing files contains metadata about a file and its offset in the corresponding NAR. +//! +//! NOTE: LS entries does not offer any integrity field to validate the retrieved file at the provided +//! offset. Validating the contents is the caller's responsibility. + +use std::collections::HashMap; + +use serde::Deserialize; + +#[cfg(test)] +mod test; + +#[derive(Debug, Deserialize)] +#[serde(tag = "type", rename_all = "lowercase")] +pub enum ListingEntry { + Regular { + size: u64, + #[serde(default)] + executable: bool, + #[serde(rename = "narOffset")] + nar_offset: u64, + }, + Directory { + entries: HashMap<String, ListingEntry>, + }, + Symlink { + target: String, + }, +} + +#[derive(Debug)] +pub struct ListingVersion<const V: u8>; + +#[derive(Debug, thiserror::Error)] +#[error("Invalid version: {0}")] +struct ListingVersionError(u8); + +impl<'de, const V: u8> Deserialize<'de> for ListingVersion<V> { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + let value = u8::deserialize(deserializer)?; + if value == V { + Ok(ListingVersion::<V>) + } else { + Err(serde::de::Error::custom(ListingVersionError(value))) + } + } +} + +#[derive(Debug, Deserialize)] +#[serde(untagged)] +#[non_exhaustive] +pub enum Listing { + V1 { + root: ListingEntry, + version: ListingVersion<1>, + }, +} |