noosphere_collections/hamt/
hash_algorithm.rs

1// Adapted for Noosphere from https://github.com/filecoin-project/ref-fvm
2// Source copyright and license:
3// Copyright 2019-2022 ChainSafe Systems
4// SPDX-License-Identifier: Apache-2.0, MIT
5
6use std::hash::Hasher;
7
8use sha2::{Digest, Sha256 as Sha256Hasher};
9
10pub use forest_hash_utils::Hash;
11
12use super::TargetConditionalSendSync;
13
14pub type HashedKey = [u8; 32];
15
16/// Algorithm used as the hasher for the Hamt.
17pub trait HashAlgorithm: TargetConditionalSendSync {
18    fn hash<X: ?Sized>(key: &X) -> HashedKey
19    where
20        X: Hash;
21}
22
23/// Type is needed because the Sha256 hasher does not implement `std::hash::Hasher`
24#[derive(Default)]
25struct Sha2HasherWrapper(Sha256Hasher);
26
27impl Hasher for Sha2HasherWrapper {
28    fn finish(&self) -> u64 {
29        // u64 hash not used in hamt
30        0
31    }
32
33    fn write(&mut self, bytes: &[u8]) {
34        self.0.update(bytes);
35    }
36}
37
38/// Sha256 hashing algorithm used for hashing keys in the Hamt.
39#[derive(Debug)]
40pub enum Sha256 {}
41
42impl HashAlgorithm for Sha256 {
43    fn hash<X: ?Sized>(key: &X) -> HashedKey
44    where
45        X: Hash,
46    {
47        let mut hasher = Sha2HasherWrapper::default();
48        key.hash(&mut hasher);
49        hasher.0.finalize().into()
50    }
51}
52
53#[cfg(feature = "identity")]
54#[derive(Default)]
55pub struct IdentityHasher {
56    bz: HashedKey,
57}
58#[cfg(feature = "identity")]
59impl Hasher for IdentityHasher {
60    fn finish(&self) -> u64 {
61        // u64 hash not used in hamt
62        0
63    }
64
65    fn write(&mut self, bytes: &[u8]) {
66        for (i, byte) in bytes.iter().take(self.bz.len()).enumerate() {
67            self.bz[i] = *byte;
68        }
69    }
70}
71
72/// Identity hashing algorithm used for hashing keys in the Hamt. This should only be used
73/// for testing. The hash is just the first 32 bytes of the serialized key.
74#[cfg(feature = "identity")]
75#[derive(Debug)]
76pub enum Identity {}
77
78#[cfg(feature = "identity")]
79impl HashAlgorithm for Identity {
80    fn hash<X: ?Sized>(key: &X) -> HashedKey
81    where
82        X: Hash,
83    {
84        let mut ident_hasher = IdentityHasher::default();
85        key.hash(&mut ident_hasher);
86        ident_hasher.bz
87    }
88}