1#![cfg_attr(feature = "arb", allow(unreachable_code))] #![cfg_attr(docsrs, feature(doc_cfg))]
3#![cfg_attr(not(feature = "std"), no_std)]
4
5mod hasher_impl;
14
15pub use multihash_derive::MultihashDigest;
16
17#[cfg(feature = "blake2b")]
18#[cfg_attr(docsrs, doc(cfg(feature = "blake2b")))]
19pub use crate::hasher_impl::blake2b::{Blake2b256, Blake2b512, Blake2bHasher};
20#[cfg(feature = "blake2s")]
21#[cfg_attr(docsrs, doc(cfg(feature = "blake2s")))]
22pub use crate::hasher_impl::blake2s::{Blake2s128, Blake2s256, Blake2sHasher};
23#[cfg(feature = "blake3")]
24#[cfg_attr(docsrs, doc(cfg(feature = "blake3")))]
25pub use crate::hasher_impl::blake3::{Blake3Hasher, Blake3_256};
26#[cfg(feature = "ripemd")]
27#[cfg_attr(docsrs, doc(cfg(feature = "ripemd")))]
28pub use crate::hasher_impl::ripemd::{Ripemd160, Ripemd256, Ripemd320};
29#[cfg(feature = "sha1")]
30#[cfg_attr(docsrs, doc(cfg(feature = "sha1")))]
31pub use crate::hasher_impl::sha1::Sha1;
32#[cfg(feature = "sha2")]
33#[cfg_attr(docsrs, doc(cfg(feature = "sha2")))]
34pub use crate::hasher_impl::sha2::{Sha2_256, Sha2_512};
35#[cfg(feature = "sha3")]
36#[cfg_attr(docsrs, doc(cfg(feature = "sha3")))]
37pub use crate::hasher_impl::sha3::{
38 Keccak224, Keccak256, Keccak384, Keccak512, Sha3_224, Sha3_256, Sha3_384, Sha3_512,
39};
40#[cfg(feature = "strobe")]
41#[cfg_attr(docsrs, doc(cfg(feature = "strobe")))]
42pub use crate::hasher_impl::strobe::{Strobe256, Strobe512, StrobeHasher};
43
44#[cfg_attr(feature = "arb", derive(arbitrary::Arbitrary))]
51#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
52#[derive(Copy, Clone, Debug, Eq, MultihashDigest, PartialEq)]
53#[mh(alloc_size = 64)]
54pub enum Code {
55 #[cfg(feature = "sha2")]
57 #[cfg_attr(docsrs, doc(cfg(feature = "sha2")))]
58 #[mh(code = 0x12, hasher = crate::Sha2_256)]
59 Sha2_256,
60 #[cfg(feature = "sha2")]
62 #[cfg_attr(docsrs, doc(cfg(feature = "sha2")))]
63 #[mh(code = 0x13, hasher = crate::Sha2_512)]
64 Sha2_512,
65 #[cfg(feature = "sha3")]
67 #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))]
68 #[mh(code = 0x17, hasher = crate::Sha3_224)]
69 Sha3_224,
70 #[cfg(feature = "sha3")]
72 #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))]
73 #[mh(code = 0x16, hasher = crate::Sha3_256)]
74 Sha3_256,
75 #[cfg(feature = "sha3")]
77 #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))]
78 #[mh(code = 0x15, hasher = crate::Sha3_384)]
79 Sha3_384,
80 #[cfg(feature = "sha3")]
82 #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))]
83 #[mh(code = 0x14, hasher = crate::Sha3_512)]
84 Sha3_512,
85 #[cfg(feature = "sha3")]
87 #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))]
88 #[mh(code = 0x1a, hasher = crate::Keccak224)]
89 Keccak224,
90 #[cfg(feature = "sha3")]
92 #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))]
93 #[mh(code = 0x1b, hasher = crate::Keccak256)]
94 Keccak256,
95 #[cfg(feature = "sha3")]
97 #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))]
98 #[mh(code = 0x1c, hasher = crate::Keccak384)]
99 Keccak384,
100 #[cfg(feature = "sha3")]
102 #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))]
103 #[mh(code = 0x1d, hasher = crate::Keccak512)]
104 Keccak512,
105 #[cfg(feature = "blake2b")]
107 #[cfg_attr(docsrs, doc(cfg(feature = "blake2b")))]
108 #[mh(code = 0xb220, hasher = crate::Blake2b256)]
109 Blake2b256,
110 #[cfg(feature = "blake2b")]
112 #[cfg_attr(docsrs, doc(cfg(feature = "blake2b")))]
113 #[mh(code = 0xb240, hasher = crate::Blake2b512)]
114 Blake2b512,
115 #[cfg(feature = "blake2s")]
117 #[cfg_attr(docsrs, doc(cfg(feature = "blake2s")))]
118 #[mh(code = 0xb250, hasher = crate::Blake2s128)]
119 Blake2s128,
120 #[cfg(feature = "blake2s")]
122 #[cfg_attr(docsrs, doc(cfg(feature = "blake2s")))]
123 #[mh(code = 0xb260, hasher = crate::Blake2s256)]
124 Blake2s256,
125 #[cfg(feature = "blake3")]
127 #[cfg_attr(docsrs, doc(cfg(feature = "blake3")))]
128 #[mh(code = 0x1e, hasher = crate::Blake3_256)]
129 Blake3_256,
130 #[cfg(feature = "ripemd")]
132 #[cfg_attr(docsrs, doc(cfg(feature = "ripemd")))]
133 #[mh(code = 0x1053, hasher = crate::Ripemd160)]
134 Ripemd160,
135 #[cfg(feature = "ripemd")]
137 #[cfg_attr(docsrs, doc(cfg(feature = "ripemd")))]
138 #[mh(code = 0x1054, hasher = crate::Ripemd256)]
139 Ripemd256,
140 #[cfg(feature = "ripemd")]
142 #[cfg_attr(docsrs, doc(cfg(feature = "ripemd")))]
143 #[mh(code = 0x1055, hasher = crate::Ripemd320)]
144 Ripemd320,
145}
146
147#[cfg(all(test, any(feature = "sha2", feature = "sha3")))]
148mod tests {
149 use super::*;
150 #[cfg(feature = "sha3")]
151 use crate::hasher_impl::sha3::{Sha3_256, Sha3_512};
152 #[cfg(feature = "sha3")]
153 use multihash_derive::Hasher;
154 #[cfg(feature = "sha2")]
155 use multihash_derive::{Multihash, MultihashDigest};
156
157 #[test]
158 #[cfg(feature = "sha3")]
159 fn test_hasher_256() {
160 let mut hasher = Sha3_256::default();
161 hasher.update(b"hello world");
162 let digest = hasher.finalize();
163 let hash = Code::Sha3_256.wrap(digest).unwrap();
164 let hash2 = Code::Sha3_256.digest(b"hello world");
165 assert_eq!(hash.code(), u64::from(Code::Sha3_256));
166 assert_eq!(hash.size(), 32);
167 assert_eq!(hash.digest(), digest);
168 assert_eq!(hash, hash2);
169 }
170
171 #[test]
172 #[cfg(feature = "sha3")]
173 fn test_hasher_512() {
174 let mut hasher = Sha3_512::default();
175 hasher.update(b"hello world");
176 let digest = hasher.finalize();
177 let hash = Code::Sha3_512.wrap(digest).unwrap();
178 let hash2 = Code::Sha3_512.digest(b"hello world");
179 assert_eq!(hash.code(), u64::from(Code::Sha3_512));
180 assert_eq!(hash.size(), 64);
181 assert_eq!(hash.digest(), digest);
182 assert_eq!(hash, hash2);
183 }
184
185 #[test]
186 #[cfg(feature = "sha2")]
187 fn roundtrip() {
188 let hash = Code::Sha2_256.digest(b"hello world");
189 let mut buf = [0u8; 35];
190 let written = hash.write(&mut buf[..]).unwrap();
191 let hash2 = Multihash::<32>::read(&buf[..]).unwrap();
192 assert_eq!(hash, hash2);
193 assert_eq!(hash.encoded_len(), written);
194 }
195
196 #[test]
197 #[cfg(feature = "sha2")]
198 fn test_truncate_down() {
199 let hash = Code::Sha2_256.digest(b"hello world");
200 let small = hash.truncate(20);
201 assert_eq!(small.size(), 20);
202 }
203
204 #[test]
205 #[cfg(feature = "sha2")]
206 fn test_truncate_up() {
207 let hash = Code::Sha2_256.digest(b"hello world");
208 let small = hash.truncate(100);
209 assert_eq!(small.size(), 32);
210 }
211
212 #[test]
213 #[cfg(feature = "sha2")]
214 fn test_resize_fits() {
215 let hash = Code::Sha2_256.digest(b"hello world");
216 let _: Multihash<32> = hash.resize().unwrap();
217 }
218
219 #[test]
220 #[cfg(feature = "sha2")]
221 fn test_resize_up() {
222 let hash = Code::Sha2_256.digest(b"hello world");
223 let _: Multihash<100> = hash.resize().unwrap();
224 }
225
226 #[test]
227 #[cfg(feature = "sha2")]
228 fn test_resize_truncate() {
229 let hash = Code::Sha2_256.digest(b"hello world");
230 hash.resize::<20>().unwrap_err();
231 }
232}