feat(nix-compat/nixbase32): use data_encoding::DecodeError

Rather than having our own error type, just make decoding errors use
the same common error type.

Change-Id: Ie2c86972f3745c695253adc3214444ac0ab8db6e
Reviewed-on: https://cl.tvl.fyi/c/depot/+/9995
Reviewed-by: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
This commit is contained in:
edef 2023-11-10 18:32:40 +00:00
parent 7e317cfded
commit 4218e4dc0e
4 changed files with 28 additions and 30 deletions

View file

@ -465,7 +465,7 @@ pub enum Error {
MissingPrefixForHash(String), MissingPrefixForHash(String),
#[error("unable to decode {0}: {1}")] #[error("unable to decode {0}: {1}")]
UnableToDecodeHash(String, nixbase32::Nixbase32DecodeError), UnableToDecodeHash(String, data_encoding::DecodeError),
#[error("unable to parse signature #{0}: {1}")] #[error("unable to parse signature #{0}: {1}")]
UnableToParseSignature(usize, SignatureError), UnableToParseSignature(usize, SignatureError),

View file

@ -9,21 +9,10 @@
use std::fmt::Write; use std::fmt::Write;
use thiserror::Error; use data_encoding::{DecodeError, DecodeKind};
const ALPHABET: &[u8; 32] = b"0123456789abcdfghijklmnpqrsvwxyz"; const ALPHABET: &[u8; 32] = b"0123456789abcdfghijklmnpqrsvwxyz";
/// Errors that can occur while decoding nixbase32-encoded data.
#[derive(Debug, Eq, PartialEq, Error)]
pub enum Nixbase32DecodeError {
#[error("character {0:x} not in alphabet")]
CharacterNotInAlphabet(u8),
#[error("nonzero carry")]
NonzeroCarry,
#[error("invalid length")]
InvalidLength,
}
/// Returns encoded input /// Returns encoded input
pub fn encode(input: &[u8]) -> String { pub fn encode(input: &[u8]) -> String {
let output_len = encode_len(input.len()); let output_len = encode_len(input.len());
@ -69,7 +58,7 @@ const BASE32_ORD: [u8; 256] = {
}; };
/// Returns decoded input /// Returns decoded input
pub fn decode(input: impl AsRef<[u8]>) -> Result<Vec<u8>, Nixbase32DecodeError> { pub fn decode(input: impl AsRef<[u8]>) -> Result<Vec<u8>, DecodeError> {
let input = input.as_ref(); let input = input.as_ref();
let output_len = decode_len(input.len()); let output_len = decode_len(input.len());
@ -79,13 +68,14 @@ pub fn decode(input: impl AsRef<[u8]>) -> Result<Vec<u8>, Nixbase32DecodeError>
Ok(output) Ok(output)
} }
pub fn decode_fixed<const K: usize>( pub fn decode_fixed<const K: usize>(input: impl AsRef<[u8]>) -> Result<[u8; K], DecodeError> {
input: impl AsRef<[u8]>,
) -> Result<[u8; K], Nixbase32DecodeError> {
let input = input.as_ref(); let input = input.as_ref();
if input.len() != encode_len(K) { if input.len() != encode_len(K) {
return Err(Nixbase32DecodeError::InvalidLength); return Err(DecodeError {
position: input.len().min(encode_len(K)),
kind: DecodeKind::Length,
});
} }
let mut output = [0; K]; let mut output = [0; K];
@ -93,7 +83,7 @@ pub fn decode_fixed<const K: usize>(
Ok(output) Ok(output)
} }
fn decode_inner(input: &[u8], output: &mut [u8]) -> Result<(), Nixbase32DecodeError> { fn decode_inner(input: &[u8], output: &mut [u8]) -> Result<(), DecodeError> {
// loop over all characters in reverse, and keep the iteration count in n. // loop over all characters in reverse, and keep the iteration count in n.
let mut carry = 0; let mut carry = 0;
let mut mask = 0; let mut mask = 0;
@ -111,22 +101,27 @@ fn decode_inner(input: &[u8], output: &mut [u8]) -> Result<(), Nixbase32DecodeEr
} }
if mask == 0xFF { if mask == 0xFF {
let c = find_invalid(input); return Err(DecodeError {
return Err(Nixbase32DecodeError::CharacterNotInAlphabet(c)); position: find_invalid(input),
kind: DecodeKind::Symbol,
});
} }
// if we're at the end, but have a nonzero carry, the encoding is invalid. // if we're at the end, but have a nonzero carry, the encoding is invalid.
if carry != 0 { if carry != 0 {
return Err(Nixbase32DecodeError::NonzeroCarry); return Err(DecodeError {
position: 0,
kind: DecodeKind::Trailing,
});
} }
Ok(()) Ok(())
} }
fn find_invalid(input: &[u8]) -> u8 { fn find_invalid(input: &[u8]) -> usize {
for &c in input { for (i, &c) in input.iter().enumerate() {
if !ALPHABET.contains(&c) { if !ALPHABET.contains(&c) {
return c; return i;
} }
} }
@ -187,7 +182,10 @@ mod tests {
); );
assert_eq!( assert_eq!(
super::decode_fixed::<32>("00").unwrap_err(), super::decode_fixed::<32>("00").unwrap_err(),
super::Nixbase32DecodeError::InvalidLength super::DecodeError {
position: 2,
kind: super::DecodeKind::Length
}
); );
} }

View file

@ -92,7 +92,7 @@ pub enum Error {
#[error("invalid base16 encoding: {0}")] #[error("invalid base16 encoding: {0}")]
InvalidBase16Encoding(data_encoding::DecodeError), InvalidBase16Encoding(data_encoding::DecodeError),
#[error("invalid base32 encoding: {0}")] #[error("invalid base32 encoding: {0}")]
InvalidBase32Encoding(nixbase32::Nixbase32DecodeError), InvalidBase32Encoding(data_encoding::DecodeError),
#[error("invalid base64 encoding: {0}")] #[error("invalid base64 encoding: {0}")]
InvalidBase64Encoding(data_encoding::DecodeError), InvalidBase64Encoding(data_encoding::DecodeError),
#[error("conflicting hash algo: {0} (hash_algo) vs {1} (inline)")] #[error("conflicting hash algo: {0} (hash_algo) vs {1} (inline)")]

View file

@ -1,5 +1,5 @@
use crate::nixbase32::{self, Nixbase32DecodeError}; use crate::nixbase32;
use data_encoding::BASE64; use data_encoding::{DecodeError, BASE64};
use std::{ use std::{
fmt, fmt,
path::PathBuf, path::PathBuf,
@ -28,7 +28,7 @@ pub enum Error {
#[error("Dash is missing between hash and name")] #[error("Dash is missing between hash and name")]
MissingDash, MissingDash,
#[error("Hash encoding is invalid: {0}")] #[error("Hash encoding is invalid: {0}")]
InvalidHashEncoding(Nixbase32DecodeError), InvalidHashEncoding(DecodeError),
#[error("Invalid length")] #[error("Invalid length")]
InvalidLength, InvalidLength,
#[error( #[error(