dicom_anonymization/
hasher.rs

1use num_bigint::{BigInt, ParseBigIntError};
2use num_traits::Num;
3use thiserror::Error;
4
5#[derive(Error, Debug, PartialEq)]
6pub enum Error {
7    #[error("Invalid input: {}", .0.to_lowercase())]
8    InvalidInput(String),
9}
10
11impl From<ParseBigIntError> for Error {
12    fn from(err: ParseBigIntError) -> Self {
13        Error::InvalidInput(format!("{err}"))
14    }
15}
16
17pub type Result<T, E = Error> = std::result::Result<T, E>;
18
19// signature type for hash functions
20pub type HashFn = fn(&str) -> Result<BigInt>;
21
22// blake3 implementation of a hash function
23pub fn blake3_hash_fn(input: &str) -> Result<BigInt> {
24    let bytes = input.as_bytes();
25    let hash = blake3::hash(bytes);
26    let hash_as_number = BigInt::from_str_radix(hash.to_hex().as_str(), 16)?;
27    Ok(hash_as_number)
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    #[test]
35    fn test_hello_world() {
36        let result = blake3_hash_fn("hello, world!").unwrap();
37        assert!(!result.to_string().is_empty());
38    }
39
40    #[test]
41    fn test_empty_string() {
42        let result = blake3_hash_fn("").unwrap();
43        assert!(!result.to_string().is_empty());
44    }
45
46    #[test]
47    fn test_special_characters() {
48        let result = blake3_hash_fn("_!@€±§%^!&@*_+{}:?><,.;").unwrap();
49        assert!(!result.to_string().is_empty());
50    }
51
52    #[test]
53    fn test_same_result_for_same_input() {
54        let result1 = blake3_hash_fn("abc").unwrap();
55        let result2 = blake3_hash_fn("abc").unwrap();
56        assert_eq!(result1, result2);
57    }
58
59    #[test]
60    fn test_different_result_for_different_input() {
61        let result1 = blake3_hash_fn("abc").unwrap();
62        let result2 = blake3_hash_fn("def").unwrap();
63        assert_ne!(result1, result2);
64    }
65}