1mod error;
25mod serde;
26
27pub use error::Error;
28
29#[deprecated(since = "0.18.0", note = "Use `multihash::Multihash instead.")]
31pub type MultihashGeneric<const N: usize> = Multihash<N>;
32
33use {
34 crate::varint::{self, encode as varint_encode},
35 alloc::vec::Vec,
36 core::{convert::TryInto, fmt::Debug},
37 core2::io,
38};
39
40#[derive(Clone, Copy, Debug, Eq, Ord, PartialOrd)]
63pub struct Multihash<const S: usize> {
64 code: u64,
66 size: u8,
68 digest: [u8; S],
70}
71
72impl<const S: usize> Default for Multihash<S> {
73 fn default() -> Self {
74 Self {
75 code: 0,
76 size: 0,
77 digest: [0; S],
78 }
79 }
80}
81
82impl<const S: usize> Multihash<S> {
83 pub const fn wrap(code: u64, input_digest: &[u8]) -> Result<Self, Error> {
85 if input_digest.len() > S {
86 return Err(Error::invalid_size(input_digest.len() as _));
87 }
88 let size = input_digest.len();
89 let mut digest = [0; S];
90 let mut i = 0;
91 while i < size {
92 digest[i] = input_digest[i];
93 i += 1;
94 }
95 Ok(Self {
96 code,
97 size: size as u8,
98 digest,
99 })
100 }
101
102 pub const fn code(&self) -> u64 {
104 self.code
105 }
106
107 pub const fn size(&self) -> u8 {
109 self.size
110 }
111
112 pub fn digest(&self) -> &[u8] {
114 &self.digest[..self.size as usize]
115 }
116
117 pub fn read<R: io::Read>(r: R) -> Result<Self, Error>
119 where
120 Self: Sized,
121 {
122 let (code, size, digest) = read_multihash(r)?;
123 Ok(Self { code, size, digest })
124 }
125
126 pub fn from_bytes(mut bytes: &[u8]) -> Result<Self, Error>
131 where
132 Self: Sized,
133 {
134 let result = Self::read(&mut bytes)?;
135 if !bytes.is_empty() {
137 return Err(Error::invalid_size(bytes.len().try_into().expect(
138 "Currently the maximum size is 255, therefore always fits into usize",
139 )));
140 }
141
142 Ok(result)
143 }
144
145 pub fn write<W: io::Write>(&self, w: W) -> Result<usize, Error> {
147 write_multihash(w, self.code(), self.size(), self.digest())
148 }
149
150 pub fn encoded_len(&self) -> usize {
152 let mut code_buf = varint_encode::u64_buffer();
153 let code = varint_encode::u64(self.code, &mut code_buf);
154
155 let mut size_buf = varint_encode::u8_buffer();
156 let size = varint_encode::u8(self.size, &mut size_buf);
157
158 code.len() + size.len() + usize::from(self.size)
159 }
160
161 pub fn to_bytes(&self) -> Vec<u8> {
163 let mut bytes = Vec::with_capacity(self.size().into());
164 let written = self
165 .write(&mut bytes)
166 .expect("writing to a vec should never fail");
167 debug_assert_eq!(written, bytes.len());
168 bytes
169 }
170
171 pub fn truncate(&self, size: u8) -> Self {
176 let mut mh = *self;
177 mh.size = mh.size.min(size);
178 mh
179 }
180
181 pub fn resize<const R: usize>(&self) -> Result<Multihash<R>, Error> {
185 let size = self.size as usize;
186 if size > R {
187 return Err(Error::invalid_size(self.size as u64));
188 }
189 let mut mh = Multihash {
190 code: self.code,
191 size: self.size,
192 digest: [0; R],
193 };
194 mh.digest[..size].copy_from_slice(&self.digest[..size]);
195 Ok(mh)
196 }
197
198 pub fn into_inner(self) -> (u64, [u8; S], u8) {
203 let Self { code, digest, size } = self;
204 (code, digest, size)
205 }
206}
207
208#[allow(clippy::derived_hash_with_manual_eq)]
210impl<const S: usize> core::hash::Hash for Multihash<S> {
211 fn hash<T: core::hash::Hasher>(&self, state: &mut T) {
212 self.code.hash(state);
213 self.digest().hash(state);
214 }
215}
216
217impl<const S: usize> From<Multihash<S>> for Vec<u8> {
218 fn from(multihash: Multihash<S>) -> Self {
219 multihash.to_bytes()
220 }
221}
222
223impl<const A: usize, const B: usize> PartialEq<Multihash<B>> for Multihash<A> {
224 fn eq(&self, other: &Multihash<B>) -> bool {
225 self.code == other.code && self.digest() == other.digest()
228 }
229}
230
231impl<const S: usize> scale::Encode for Multihash<S> {
232 fn encode_to<EncOut: scale::Output + ?Sized>(&self, dest: &mut EncOut) {
233 self.code.encode_to(dest);
234 self.size.encode_to(dest);
235 dest.write(self.digest());
243 }
244}
245
246impl<const S: usize> scale::EncodeLike for Multihash<S> {}
247
248impl<const S: usize> scale::Decode for Multihash<S> {
249 fn decode<DecIn: scale::Input>(
250 input: &mut DecIn,
251 ) -> Result<Self, scale::Error> {
252 let mut mh = Multihash {
253 code: scale::Decode::decode(input)?,
254 size: scale::Decode::decode(input)?,
255 digest: [0; S],
256 };
257 if mh.size as usize > S {
258 return Err(scale::Error::from("invalid size"));
259 }
260 input.read(&mut mh.digest[..mh.size as usize])?;
262 Ok(mh)
263 }
264}
265
266fn write_multihash<W>(
268 mut w: W,
269 code: u64,
270 size: u8,
271 digest: &[u8],
272) -> Result<usize, Error>
273where
274 W: io::Write,
275{
276 let mut code_buf = varint_encode::u64_buffer();
277 let code = varint_encode::u64(code, &mut code_buf);
278
279 let mut size_buf = varint_encode::u8_buffer();
280 let size = varint_encode::u8(size, &mut size_buf);
281
282 let written = code.len() + size.len() + digest.len();
283
284 w.write_all(code).map_err(error::io_to_multihash_error)?;
285 w.write_all(size).map_err(error::io_to_multihash_error)?;
286 w.write_all(digest).map_err(error::io_to_multihash_error)?;
287
288 Ok(written)
289}
290
291fn read_multihash<R, const S: usize>(
299 mut r: R,
300) -> Result<(u64, u8, [u8; S]), Error>
301where
302 R: io::Read,
303{
304 let code = read_u64(&mut r)?;
305 let size = read_u64(&mut r)?;
306
307 if size > S as u64 || size > u8::MAX as u64 {
308 return Err(Error::invalid_size(size));
309 }
310
311 let mut digest = [0; S];
312 r.read_exact(&mut digest[..size as usize])
313 .map_err(error::io_to_multihash_error)?;
314 Ok((code, size as u8, digest))
315}
316
317pub(crate) fn read_u64<R: io::Read>(mut r: R) -> Result<u64, Error> {
318 use varint::decode;
319 let mut b = varint_encode::u64_buffer();
320 for i in 0..b.len() {
321 let n = r
322 .read(&mut (b[i..i + 1]))
323 .map_err(error::io_to_multihash_error)?;
324 if n == 0 {
325 return Err(Error::insufficient_varint_bytes());
326 } else if decode::is_last(b[i]) {
327 return decode::u64(&b[..=i])
328 .map(|decoded| decoded.0)
329 .map_err(error::varint_decode_to_multihash_error);
330 }
331 }
332 Err(Error::varint_overflow())
333}
334
335#[cfg(test)]
336mod tests {
337 use super::*;
338
339 #[test]
340 fn test_scale() {
341 use scale::{Decode, Encode};
342
343 let mh1 = Multihash::<32>::wrap(0, b"hello world").unwrap();
344 let mh1_bytes = mh1.encode();
347 let mh2: Multihash<32> = Decode::decode(&mut &mh1_bytes[..]).unwrap();
349 assert_eq!(mh1, mh2);
350
351 let mh3 = Multihash::<64>::wrap(0, b"hello world").unwrap();
352 let mh3_bytes = mh3.encode();
355 let mh4: Multihash<64> = Decode::decode(&mut &mh3_bytes[..]).unwrap();
357 assert_eq!(mh3, mh4);
358
359 assert_eq!(mh1_bytes, mh3_bytes);
360 }
361
362 #[test]
363 fn test_eq_sizes() {
364 let mh1 = Multihash::<32>::default();
365 let mh2 = Multihash::<64>::default();
366 assert_eq!(mh1, mh2);
367 }
368
369 #[test]
370 fn decode_non_minimal_error() {
371 let data = [241, 0, 0, 0, 0, 0, 128, 132, 132, 132, 58];
373 let result = read_u64(&data[..]);
374 assert!(result.is_err());
375 }
376}