1mod implementations;
2mod methods;
3
4use ps_ecc::ReedSolomon;
5
6use crate::{HashError, HASH_SIZE_BIN, PARITY};
7
8pub const RS: ReedSolomon = match ReedSolomon::new(PARITY) {
9 Ok(rs) => rs,
10 Err(_) => panic!("Failed to construct Reed-Solomon codec."),
11};
12
13#[derive(Clone, Copy)]
14#[repr(transparent)]
15pub struct Hash {
16 pub(crate) inner: [u8; HASH_SIZE_BIN],
17}
18
19#[inline]
20pub fn hash(data: impl AsRef<[u8]>) -> Result<Hash, HashError> {
21 Hash::hash(data)
22}
23
24#[cfg(test)]
25#[allow(clippy::expect_used)]
26mod tests {
27 use super::{hash, Hash, HASH_SIZE_BIN, PARITY, RS};
28
29 #[test]
30 fn rs_codec_is_valid() {
31 assert_eq!(RS.parity(), PARITY);
32 }
33
34 #[test]
36 fn rs_codec_parity_matches_constant() {
37 assert_eq!(RS.parity(), 7);
38 }
39
40 #[test]
41 fn hash_struct_has_correct_size() {
42 assert_eq!(std::mem::size_of::<Hash>(), HASH_SIZE_BIN);
43 }
44
45 #[test]
46 fn hash_struct_is_copy() {
47 fn assert_copy<T: Copy>() {}
48 assert_copy::<Hash>();
49 }
50
51 #[test]
52 fn hash_struct_is_clone() {
53 fn assert_clone<T: Clone>() {}
54 assert_clone::<Hash>();
55 }
56
57 #[test]
58 fn hash_function_delegates_to_method() {
59 let data = b"test data";
60 let via_fn = hash(data).expect("hashing should succeed");
61 let via_method = Hash::hash(data).expect("hashing should succeed");
62 assert_eq!(via_fn, via_method);
63 }
64
65 #[test]
66 fn hash_function_returns_ok_for_empty() {
67 assert!(hash(b"").is_ok());
68 }
69
70 #[test]
71 fn hash_function_returns_ok_for_non_empty() {
72 assert!(hash(b"non-empty").is_ok());
73 }
74
75 #[test]
76 fn hash_inner_field_has_correct_size() {
77 let h = hash(b"test").expect("hashing should succeed");
78 assert_eq!(h.inner.len(), HASH_SIZE_BIN);
79 }
80}