1pub mod prelude {
11 pub use super::MultihashCode;
12 pub use multihash_codetable::MultihashDigest as _;
13}
14
15use multihash_derive::{Hasher, MultihashDigest};
16
17#[derive(Clone, Copy, Debug, Eq, MultihashDigest, PartialEq)]
19#[mh(alloc_size = 64)]
20pub enum MultihashCode {
21 #[mh(code = 0x0, hasher = IdentityHasher::<64>)]
22 Identity,
23 #[mh(code = 0x12, hasher = multihash_codetable::Sha2_256)]
25 Sha2_256,
26 #[mh(code = 0x13, hasher = multihash_codetable::Sha2_512)]
28 Sha2_512,
29 #[mh(code = 0x17, hasher = multihash_codetable::Sha3_224)]
31 Sha3_224,
32 #[mh(code = 0x16, hasher = multihash_codetable::Sha3_256)]
34 Sha3_256,
35 #[mh(code = 0x15, hasher = multihash_codetable::Sha3_384)]
37 Sha3_384,
38 #[mh(code = 0x14, hasher = multihash_codetable::Sha3_512)]
40 Sha3_512,
41 #[mh(code = 0x1a, hasher = multihash_codetable::Keccak224)]
43 Keccak224,
44 #[mh(code = 0x1b, hasher = multihash_codetable::Keccak256)]
46 Keccak256,
47 #[mh(code = 0x1c, hasher = multihash_codetable::Keccak384)]
49 Keccak384,
50 #[mh(code = 0x1d, hasher = multihash_codetable::Keccak512)]
52 Keccak512,
53 #[mh(code = 0xb220, hasher = multihash_codetable::Blake2b256)]
55 Blake2b256,
56 #[mh(code = 0xb240, hasher = multihash_codetable::Blake2b512)]
58 Blake2b512,
59 #[mh(code = 0xb250, hasher = multihash_codetable::Blake2s128)]
61 Blake2s128,
62 #[mh(code = 0xb260, hasher = multihash_codetable::Blake2s256)]
64 Blake2s256,
65 #[mh(code = 0x1e, hasher = multihash_codetable::Blake3_256)]
67 Blake3_256,
68 #[mh(code = 0x1053, hasher = multihash_codetable::Ripemd160)]
70 Ripemd160,
71 #[mh(code = 0x1054, hasher = multihash_codetable::Ripemd256)]
73 Ripemd256,
74 #[mh(code = 0x1055, hasher = multihash_codetable::Ripemd320)]
76 Ripemd320,
77}
78
79impl MultihashCode {
80 pub fn digest_byte_stream<R: std::io::Read>(&self, bytes: &mut R) -> anyhow::Result<Multihash> {
82 fn hash<'a, H: Hasher, R: std::io::Read>(
83 hasher: &'a mut H,
84 bytes: &'a mut R,
85 ) -> anyhow::Result<&'a [u8]> {
86 let mut buf = [0; 1024];
87 loop {
88 let n = bytes.read(&mut buf)?;
89 if n == 0 {
90 break;
91 }
92 if let Some(b) = buf.get(0..n) {
93 hasher.update(b);
94 }
95 }
96 Ok(hasher.finalize())
97 }
98
99 Ok(match self {
100 Self::Sha2_256 => {
101 let mut hasher = multihash_codetable::Sha2_256::default();
102 self.wrap(hash(&mut hasher, bytes)?)?
103 }
104 Self::Sha2_512 => {
105 let mut hasher = multihash_codetable::Sha2_512::default();
106 self.wrap(hash(&mut hasher, bytes)?)?
107 }
108 Self::Sha3_224 => {
109 let mut hasher = multihash_codetable::Sha3_224::default();
110 self.wrap(hash(&mut hasher, bytes)?)?
111 }
112 Self::Sha3_256 => {
113 let mut hasher = multihash_codetable::Sha3_256::default();
114 self.wrap(hash(&mut hasher, bytes)?)?
115 }
116 Self::Sha3_384 => {
117 let mut hasher = multihash_codetable::Sha3_384::default();
118 self.wrap(hash(&mut hasher, bytes)?)?
119 }
120 Self::Sha3_512 => {
121 let mut hasher = multihash_codetable::Sha3_512::default();
122 self.wrap(hash(&mut hasher, bytes)?)?
123 }
124 Self::Keccak224 => {
125 let mut hasher = multihash_codetable::Keccak224::default();
126 self.wrap(hash(&mut hasher, bytes)?)?
127 }
128 Self::Keccak256 => {
129 let mut hasher = multihash_codetable::Keccak256::default();
130 self.wrap(hash(&mut hasher, bytes)?)?
131 }
132 Self::Keccak384 => {
133 let mut hasher = multihash_codetable::Keccak384::default();
134 self.wrap(hash(&mut hasher, bytes)?)?
135 }
136 Self::Keccak512 => {
137 let mut hasher = multihash_codetable::Keccak512::default();
138 self.wrap(hash(&mut hasher, bytes)?)?
139 }
140 Self::Blake2b256 => {
141 let mut hasher = multihash_codetable::Blake2b256::default();
142 self.wrap(hash(&mut hasher, bytes)?)?
143 }
144 Self::Blake2b512 => {
145 let mut hasher = multihash_codetable::Blake2b512::default();
146 self.wrap(hash(&mut hasher, bytes)?)?
147 }
148 Self::Blake2s128 => {
149 let mut hasher = multihash_codetable::Blake2s128::default();
150 self.wrap(hash(&mut hasher, bytes)?)?
151 }
152 Self::Blake2s256 => {
153 let mut hasher = multihash_codetable::Blake2s256::default();
154 self.wrap(hash(&mut hasher, bytes)?)?
155 }
156 Self::Blake3_256 => {
157 let mut hasher = multihash_codetable::Blake3_256::default();
158 self.wrap(hash(&mut hasher, bytes)?)?
159 }
160 Self::Ripemd160 => {
161 let mut hasher = multihash_codetable::Ripemd160::default();
162 self.wrap(hash(&mut hasher, bytes)?)?
163 }
164 Self::Ripemd256 => {
165 let mut hasher = multihash_codetable::Ripemd256::default();
166 self.wrap(hash(&mut hasher, bytes)?)?
167 }
168 Self::Ripemd320 => {
169 let mut hasher = multihash_codetable::Ripemd320::default();
170 self.wrap(hash(&mut hasher, bytes)?)?
171 }
172 _ => {
173 anyhow::bail!("`digest_byte_stream` is unimplemented for {self:?}");
174 }
175 })
176 }
177}
178
179#[derive(Debug)]
186pub struct IdentityHasher<const S: usize> {
187 i: usize,
188 bytes: [u8; S],
189}
190
191impl<const S: usize> Default for IdentityHasher<S> {
192 fn default() -> Self {
193 Self {
194 i: 0,
195 bytes: [0u8; S],
196 }
197 }
198}
199
200impl<const S: usize> multihash_derive::Hasher for IdentityHasher<S> {
201 fn update(&mut self, input: &[u8]) {
202 let start = self.i.min(self.bytes.len());
203 let end = (self.i + input.len()).min(self.bytes.len());
204 self.bytes[start..end].copy_from_slice(input);
205 self.i = end;
206 }
207
208 fn finalize(&mut self) -> &[u8] {
209 &self.bytes[..self.i]
210 }
211
212 fn reset(&mut self) {
213 self.i = 0
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 use std::io::Cursor;
220
221 use super::*;
222 use crate::utils::rand::forest_rng;
223 use rand::RngCore as _;
224
225 #[test]
226 fn test_digest_byte_stream() {
227 use MultihashCode::*;
228
229 for len in [0, 1, 100, 1024, 10000] {
230 let mut bytes = vec![0; len];
231 forest_rng().fill_bytes(&mut bytes);
232 let mut cursor = Cursor::new(bytes.clone());
233 for code in [
234 Sha2_256, Sha2_512, Sha3_224, Sha3_256, Sha3_384, Sha3_512, Keccak224, Keccak256,
235 Keccak384, Keccak512, Blake2b256, Blake2b512, Blake2s128, Blake2s256, Blake3_256,
236 Ripemd160, Ripemd256, Ripemd320,
237 ] {
238 cursor.set_position(0);
239 let mh1 = code.digest(&bytes);
240 let mh2 = code.digest_byte_stream(&mut cursor).unwrap();
241 assert_eq!(mh1, mh2);
242 }
243
244 cursor.set_position(0);
245 Identity.digest_byte_stream(&mut cursor).unwrap_err();
246 }
247 }
248}