1use {
5 serde::{Deserialize, Serialize},
6 sha2::{Digest, Sha256},
7 std::{fmt, mem, str::FromStr},
8 thiserror::Error,
9};
10
11pub const HASH_BYTES: usize = 32;
12#[derive(Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
13#[repr(transparent)]
14pub struct Hash(pub [u8; HASH_BYTES]);
15
16#[derive(Clone, Default)]
17pub struct Hasher {
18 hasher: Sha256,
19}
20
21impl Hasher {
22 pub fn hash(&mut self, val: &[u8]) {
23 self.hasher.update(val);
24 }
25 pub fn hashv(&mut self, vals: &[&[u8]]) {
26 for val in vals {
27 self.hash(val);
28 }
29 }
30 pub fn result(self) -> Hash {
31 #[allow(deprecated)]
35 Hash(<[u8; HASH_BYTES]>::try_from(self.hasher.finalize().as_slice()).unwrap())
36 }
37}
38
39impl AsRef<[u8]> for Hash {
40 fn as_ref(&self) -> &[u8] {
41 &self.0[..]
42 }
43}
44
45impl fmt::Debug for Hash {
46 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47 write!(f, "{}", bs58::encode(self.0).into_string())
48 }
49}
50
51impl fmt::Display for Hash {
52 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53 write!(f, "{}", bs58::encode(self.0).into_string())
54 }
55}
56
57#[derive(Debug, Clone, PartialEq, Eq, Error)]
58pub enum ParseHashError {
59 #[error("string decoded to wrong size for hash")]
60 WrongSize,
61 #[error("failed to decoded string to hash")]
62 Invalid,
63}
64
65impl FromStr for Hash {
66 type Err = ParseHashError;
67
68 fn from_str(s: &str) -> Result<Self, Self::Err> {
69 let bytes = bs58::decode(s)
70 .into_vec()
71 .map_err(|_| ParseHashError::Invalid)?;
72 if bytes.len() != mem::size_of::<Hash>() {
73 Err(ParseHashError::WrongSize)
74 } else {
75 Ok(Hash::new(&bytes))
76 }
77 }
78}
79
80impl Hash {
81 pub fn new(hash_slice: &[u8]) -> Self {
82 Hash(<[u8; HASH_BYTES]>::try_from(hash_slice).unwrap())
83 }
84
85 pub fn to_bytes(self) -> [u8; HASH_BYTES] {
86 self.0
87 }
88}
89
90pub fn hashv(vals: &[&[u8]]) -> Hash {
92 let mut hasher = Hasher::default();
95 hasher.hashv(vals);
96 hasher.result()
97}
98
99pub fn hash(val: &[u8]) -> Hash {
101 hashv(&[val])
102}