diff options
author | edef <edef@edef.eu> | 2023-10-27T07·36+0000 |
---|---|---|
committer | edef <edef@edef.eu> | 2023-10-27T12·18+0000 |
commit | fdc2e90ef2e64224f4f778f2a26bbfeb02afde2b (patch) | |
tree | 572b6cca6dcabbee3cbe1e3971b83ca45a92738e /tvix/nix-compat | |
parent | 3c0e42167fccc1d54d47bc143b85e2aef05c4d1d (diff) |
feat(tvix/nix-compat): add fixed-length base32 decoding r/6885
Change-Id: Iea9d51157c1e38e1734dc1ba752eba9b2372c61b Reviewed-on: https://cl.tvl.fyi/c/depot/+/9850 Reviewed-by: flokli <flokli@flokli.de> Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/nix-compat')
-rw-r--r-- | tvix/nix-compat/src/nixbase32.rs | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/tvix/nix-compat/src/nixbase32.rs b/tvix/nix-compat/src/nixbase32.rs index fae80cd4a042..d9821bc495bb 100644 --- a/tvix/nix-compat/src/nixbase32.rs +++ b/tvix/nix-compat/src/nixbase32.rs @@ -20,6 +20,8 @@ pub enum Nixbase32DecodeError { CharacterNotInAlphabet(u8), #[error("nonzero carry")] NonzeroCarry(), + #[error("invalid length")] + InvalidLength, } /// Returns encoded input @@ -74,6 +76,25 @@ pub fn decode(input: impl AsRef<[u8]>) -> Result<Vec<u8>, Nixbase32DecodeError> let output_len = decode_len(input.len()); let mut output: Vec<u8> = vec![0x00; output_len]; + decode_inner(input, &mut output)?; + Ok(output) +} + +pub fn decode_fixed<const K: usize>( + input: impl AsRef<[u8]>, +) -> Result<[u8; K], Nixbase32DecodeError> { + let input = input.as_ref(); + + if input.len() != encode_len(K) { + return Err(Nixbase32DecodeError::InvalidLength); + } + + let mut output = [0; K]; + decode_inner(input, &mut output)?; + Ok(output) +} + +fn decode_inner(input: &[u8], output: &mut [u8]) -> Result<(), Nixbase32DecodeError> { // loop over all characters in reverse, and keep the iteration count in n. let mut carry = 0; let mut mask = 0; @@ -100,7 +121,7 @@ pub fn decode(input: impl AsRef<[u8]>) -> Result<Vec<u8>, Nixbase32DecodeError> return Err(Nixbase32DecodeError::NonzeroCarry()); } - Ok(output) + Ok(()) } #[cold] @@ -161,6 +182,18 @@ mod tests { } #[test] + fn decode_fixed() { + assert_eq!( + super::decode_fixed("00bgd045z0d4icpbc2yyz4gx48ak44la").unwrap(), + hex!("8a12321522fd91efbd60ebb2481af88580f61600") + ); + assert_eq!( + super::decode_fixed::<32>("00").unwrap_err(), + super::Nixbase32DecodeError::InvalidLength + ); + } + + #[test] fn encode_len() { assert_eq!(super::encode_len(0), 0); assert_eq!(super::encode_len(20), 32); |