diff --git a/src/fingerprint.rs b/src/fingerprint.rs index e6dc25bf..727fc155 100644 --- a/src/fingerprint.rs +++ b/src/fingerprint.rs @@ -1,6 +1,6 @@ use super::*; -#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct Fingerprint(pub(crate) Hash); impl Fingerprint { @@ -19,9 +19,22 @@ impl Display for Fingerprint { } impl FromStr for Fingerprint { - type Err = blake3::HexError; + type Err = HashError; fn from_str(s: &str) -> Result { Ok(Self(s.parse()?)) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn uppercase_is_forbidden() { + test::HASH + .to_uppercase() + .parse::() + .unwrap_err(); + } +} diff --git a/src/hash.rs b/src/hash.rs index 5205c588..11e1a16a 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -30,10 +30,16 @@ impl From<[u8; Hash::LEN]> for Hash { } impl FromStr for Hash { - type Err = blake3::HexError; + type Err = HashError; fn from_str(s: &str) -> Result { - Ok(Self(s.parse()?)) + let hash = s.parse()?; + + if !is_lowercase_hex(s) { + return Err(hash_error::Case { hash: s }.build()); + } + + Ok(Self(hash)) } } @@ -103,4 +109,9 @@ mod tests { ); assert_eq!(serde_json::from_str::(&json).unwrap(), input); } + + #[test] + fn uppercase_is_forbidden() { + test::HASH.to_uppercase().parse::().unwrap_err(); + } } diff --git a/src/hash_error.rs b/src/hash_error.rs new file mode 100644 index 00000000..c3630b0c --- /dev/null +++ b/src/hash_error.rs @@ -0,0 +1,10 @@ +use super::*; + +#[derive(Debug, Snafu)] +#[snafu(context(suffix(false)), visibility(pub(crate)))] +pub enum HashError { + #[snafu(display("hashes must be lowercase hex: `{hash}`"))] + Case { hash: String }, + #[snafu(transparent)] + Hex { source: blake3::HexError }, +} diff --git a/src/lib.rs b/src/lib.rs index 21c5f0c4..74dba491 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,7 @@ use { fingerprint_prefix::FingerprintPrefix, format::Format, functions::{current_dir, decode_path, default, is_default, is_lowercase_hex, now}, + hash_error::HashError, index::Index, key_identifier::KeyIdentifier, key_name::KeyName, @@ -142,6 +143,7 @@ mod fingerprint_prefix; mod format; mod functions; mod hash; +mod hash_error; mod index; mod key_identifier; mod key_name;