duvet_core/
hash.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use core::{fmt, ops::Deref};
5
6#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
7#[repr(transparent)]
8pub struct Hash([u8; HASH_LEN]);
9
10impl fmt::Debug for Hash {
11    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12        write!(f, "0x")?;
13        for byte in &self.0 {
14            write!(f, "{byte:02x}")?;
15        }
16        Ok(())
17    }
18}
19
20impl Deref for Hash {
21    type Target = [u8; HASH_LEN];
22
23    fn deref(&self) -> &Self::Target {
24        &self.0
25    }
26}
27
28impl AsRef<[u8]> for Hash {
29    fn as_ref(&self) -> &[u8] {
30        &self.0
31    }
32}
33
34impl AsRef<[u8; HASH_LEN]> for Hash {
35    fn as_ref(&self) -> &[u8; HASH_LEN] {
36        &self.0
37    }
38}
39
40impl From<blake3::Hash> for Hash {
41    fn from(value: blake3::Hash) -> Self {
42        Self(value.into())
43    }
44}
45
46pub const HASH_LEN: usize = 32;
47
48#[derive(Default)]
49pub struct Hasher {
50    inner: blake3::Hasher,
51}
52
53impl Hasher {
54    pub fn hash<T: AsRef<[u8]>>(v: T) -> Hash {
55        use core::hash::Hasher as _;
56        let mut hash = Self::default();
57        hash.write(v.as_ref());
58        hash.finish()
59    }
60
61    pub fn finish(&self) -> Hash {
62        self.inner.finalize().into()
63    }
64}
65
66impl core::hash::Hasher for Hasher {
67    fn write(&mut self, bytes: &[u8]) {
68        self.inner.update(bytes);
69    }
70
71    fn finish(&self) -> u64 {
72        let mut out = [0; 8];
73        let hash = self.inner.finalize();
74        out.copy_from_slice(&hash.as_bytes()[..8]);
75        u64::from_le_bytes(out)
76    }
77}