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:
parent
7e317cfded
commit
4218e4dc0e
4 changed files with 28 additions and 30 deletions
|
@ -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),
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)")]
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Reference in a new issue