about summary refs log tree commit diff
path: root/tvix/nix-compat/src/nixbase32.rs
diff options
context:
space:
mode:
authoredef <edef@edef.eu>2023-10-27T00·06+0000
committeredef <edef@edef.eu>2023-10-27T07·31+0000
commit67b08469dbaee52a622ee84757d8875f3acdee41 (patch)
treeb0efa9923f9406024d36c5bb50dcd476c355544d /tvix/nix-compat/src/nixbase32.rs
parent4d35a56798e8f33d758582c10a82659ac77de7ca (diff)
refactor(tvix/nix-compat): clean up base32 decoding r/6881
Change-Id: I8591a3e1075f2281b7dc49f7fa9e0027062a78a5
Reviewed-on: https://cl.tvl.fyi/c/depot/+/9846
Reviewed-by: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/nix-compat/src/nixbase32.rs')
-rw-r--r--tvix/nix-compat/src/nixbase32.rs41
1 files changed, 18 insertions, 23 deletions
diff --git a/tvix/nix-compat/src/nixbase32.rs b/tvix/nix-compat/src/nixbase32.rs
index 86d900032d1a..d70e4c1a8290 100644
--- a/tvix/nix-compat/src/nixbase32.rs
+++ b/tvix/nix-compat/src/nixbase32.rs
@@ -52,7 +52,7 @@ pub fn encode(input: &[u8]) -> String {
 
 /// This maps a nixbase32-encoded character to its binary representation, which
 /// is also the index of the character in the alphabet.
-fn decode_char(encoded_char: &u8) -> Option<u8> {
+fn decode_char(encoded_char: u8) -> Option<u8> {
     Some(match encoded_char {
         b'0'..=b'9' => encoded_char - b'0',
         b'a'..=b'd' => encoded_char - b'a' + 10_u8,
@@ -69,31 +69,26 @@ pub fn decode(input: &[u8]) -> Result<Vec<u8>, Nixbase32DecodeError> {
     let mut output: Vec<u8> = vec![0x00; output_len];
 
     // loop over all characters in reverse, and keep the iteration count in n.
-    for (n, c) in input.iter().rev().enumerate() {
-        match decode_char(c) {
-            None => return Err(Nixbase32DecodeError::CharacterNotInAlphabet(*c)),
-            Some(c_decoded) => {
-                let b = n * 5;
-                let i = b / 8;
-                let j = b % 8;
-
-                let val = (c_decoded as u16).rotate_left(j as u32);
-                output[i] |= (val & 0x00ff) as u8;
-                let carry = ((val & 0xff00) >> 8) as u8;
-
-                // if we're at the end of dst…
-                if i == output_len - 1 {
-                    // but have a nonzero carry, the encoding is invalid.
-                    if carry != 0 {
-                        return Err(Nixbase32DecodeError::NonzeroCarry());
-                    }
-                } else {
-                    output[i + 1] |= carry;
-                }
-            }
+    let mut carry = 0;
+    for (n, &c) in input.iter().rev().enumerate() {
+        if let Some(digit) = decode_char(c) {
+            let b = n * 5;
+            let i = b / 8;
+            let j = b % 8;
+
+            let value = (digit as u16) << j;
+            output[i] |= value as u8 | carry;
+            carry = (value >> 8) as u8;
+        } else {
+            return Err(Nixbase32DecodeError::CharacterNotInAlphabet(c));
         }
     }
 
+    // if we're at the end, but have a nonzero carry, the encoding is invalid.
+    if carry != 0 {
+        return Err(Nixbase32DecodeError::NonzeroCarry());
+    }
+
     Ok(output)
 }