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