diff options
Diffstat (limited to 'tvix/nix-compat')
-rw-r--r-- | tvix/nix-compat/Cargo.toml | 1 | ||||
-rw-r--r-- | tvix/nix-compat/src/nixhash/mod.rs | 4 | ||||
-rw-r--r-- | tvix/nix-compat/src/nixhash/with_mode.rs | 46 |
3 files changed, 49 insertions, 2 deletions
diff --git a/tvix/nix-compat/Cargo.toml b/tvix/nix-compat/Cargo.toml index 3820ed6b1fcd..df7cc2d7b56d 100644 --- a/tvix/nix-compat/Cargo.toml +++ b/tvix/nix-compat/Cargo.toml @@ -19,6 +19,7 @@ thiserror = "1.0.38" [dev-dependencies] futures = { version = "0.3.28", default-features = false, features = ["executor"] } +lazy_static = "1.4.0" serde_json = "1.0" test-case = "2.2.2" diff --git a/tvix/nix-compat/src/nixhash/mod.rs b/tvix/nix-compat/src/nixhash/mod.rs index 3b2810b8b0bf..9586473d1b9a 100644 --- a/tvix/nix-compat/src/nixhash/mod.rs +++ b/tvix/nix-compat/src/nixhash/mod.rs @@ -65,8 +65,8 @@ impl TryFrom<(HashAlgo, &[u8])> for NixHash { } /// Constructs a new [NixHash] by specifying [HashAlgo] and digest. -// It can fail if the passed digest length doesn't match what's expected for -// the passed algo. +/// It can fail if the passed digest length doesn't match what's expected for +/// the passed algo. pub fn from_algo_and_digest(algo: HashAlgo, digest: &[u8]) -> Result<NixHash> { if digest.len() != algo.digest_length() { return Err(Error::InvalidEncodedDigestLength(digest.len(), algo)); diff --git a/tvix/nix-compat/src/nixhash/with_mode.rs b/tvix/nix-compat/src/nixhash/with_mode.rs index 86c14dc25d9c..efea3d0e6231 100644 --- a/tvix/nix-compat/src/nixhash/with_mode.rs +++ b/tvix/nix-compat/src/nixhash/with_mode.rs @@ -30,6 +30,21 @@ pub enum NixHashWithMode { } impl NixHashWithMode { + /// Construct a [NixHashWithMode] from a string containing the algo, and + /// optionally a `r:` prefix, and a digest (bytes). + pub fn from_algo_mode_hash(algo_and_mode: &str, digest: &[u8]) -> super::Result<Self> { + Ok(match algo_and_mode.strip_prefix("r:") { + Some(algo) => nixhash::NixHashWithMode::Recursive(nixhash::from_algo_and_digest( + algo.try_into()?, + &digest, + )?), + None => nixhash::NixHashWithMode::Flat(nixhash::from_algo_and_digest( + algo_and_mode.try_into()?, + &digest, + )?), + }) + } + pub fn mode(&self) -> NixHashMode { match self { Self::Flat(_) => NixHashMode::Flat, @@ -186,3 +201,34 @@ impl<'de> Deserialize<'de> for NixHashWithMode { } } } + +#[cfg(test)] +mod tests { + use crate::nixhash::{NixHash, NixHashWithMode}; + use lazy_static::lazy_static; + use test_case::test_case; + + const DIGEST_SHA256: [u8; 32] = [ + 0xa5, 0xce, 0x9c, 0x15, 0x5e, 0xd0, 0x93, 0x97, 0x61, 0x46, 0x46, 0xc9, 0x71, 0x7f, 0xc7, + 0xcd, 0x94, 0xb1, 0x02, 0x3d, 0x7b, 0x76, 0xb6, 0x18, 0xd4, 0x09, 0xe4, 0xfe, 0xfd, 0x6e, + 0x9d, 0x39, + ]; + lazy_static! { + pub static ref NIXHASH_SHA256: NixHash = NixHash::Sha256(DIGEST_SHA256); + } + + #[test_case("sha256", &DIGEST_SHA256, NixHashWithMode::Flat(NIXHASH_SHA256.clone()); "sha256 flat")] + #[test_case("r:sha256", &DIGEST_SHA256, NixHashWithMode::Recursive(NIXHASH_SHA256.clone()); "sha256 recursive")] + fn from_from_algo_mode_hash(algo_and_mode: &str, digest: &[u8], expected: NixHashWithMode) { + assert_eq!( + expected, + NixHashWithMode::from_algo_mode_hash(algo_and_mode, digest).unwrap() + ); + } + + #[test] + fn from_algo_mode_failure() { + assert!(NixHashWithMode::from_algo_mode_hash("r:sha256", &[]).is_err()); + assert!(NixHashWithMode::from_algo_mode_hash("ha256", &DIGEST_SHA256).is_err()); + } +} |