holo_hash/
hashed.rs

1use crate::HasHash;
2use crate::HashableContent;
3use crate::HoloHashOf;
4
5#[cfg(feature = "serialization")]
6use holochain_serialized_bytes::prelude::*;
7
8#[cfg(feature = "fuzzing")]
9use crate::PrimitiveHashType;
10
11/// Represents some piece of content along with its hash representation, so that
12/// hashes need not be calculated multiple times.
13/// Provides an easy constructor which consumes the content.
14// MAYBE: consider making lazy with OnceCell
15#[cfg_attr(feature = "serialization", derive(Debug, Serialize, Deserialize))]
16pub struct HoloHashed<C: HashableContent> {
17    /// The content which is hashed of type C.
18    pub content: C,
19    /// The hash of the content C.
20    pub hash: HoloHashOf<C>,
21}
22
23impl<C: HashableContent> HasHash for HoloHashed<C> {
24    type HashType = C::HashType;
25
26    fn as_hash(&self) -> &HoloHashOf<C> {
27        &self.hash
28    }
29
30    fn into_hash(self) -> HoloHashOf<C> {
31        self.hash
32    }
33}
34
35#[cfg(feature = "fuzzing")]
36impl<'a, C> arbitrary::Arbitrary<'a> for HoloHashed<C>
37where
38    C: HashableContent + arbitrary::Arbitrary<'a>,
39    C::HashType: PrimitiveHashType,
40{
41    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
42        let hash = HoloHashOf::<C>::arbitrary(u)?;
43        let content = C::arbitrary(u)?;
44        Ok(Self { content, hash })
45    }
46}
47
48impl<C> HoloHashed<C>
49where
50    C: HashableContent,
51{
52    /// Combine content with its precalculated hash
53    pub fn with_pre_hashed(content: C, hash: HoloHashOf<C>) -> Self {
54        Self { content, hash }
55    }
56
57    // NB: as_hash and into_hash are provided by the HasHash impl
58
59    /// Accessor for content
60    pub fn as_content(&self) -> &C {
61        &self.content
62    }
63
64    /// Mutable accessor for content.
65    /// Only useful for heavily mocked/fixturated data in testing.
66    /// Guaranteed the hash will no longer match the content if mutated.
67    #[cfg(feature = "test_utils")]
68    pub fn as_content_mut(&mut self) -> &mut C {
69        &mut self.content
70    }
71
72    /// Convert to content
73    pub fn into_content(self) -> C {
74        self.content
75    }
76
77    /// Deconstruct as a tuple
78    pub fn into_inner(self) -> (C, HoloHashOf<C>) {
79        (self.content, self.hash)
80    }
81
82    /// Convert to a different content type via From
83    #[cfg(feature = "test_utils")]
84    pub fn downcast<D>(&self) -> HoloHashed<D>
85    where
86        C: Clone,
87        C::HashType: crate::hash_type::HashTypeSync,
88        D: HashableContent<HashType = C::HashType> + From<C>,
89    {
90        let old_hash = &self.hash;
91        let content: D = self.content.clone().into();
92        let hashed = HoloHashed::from_content_sync_exact(content);
93        assert_eq!(&hashed.hash, old_hash);
94        hashed
95    }
96}
97
98impl<C> Clone for HoloHashed<C>
99where
100    C: HashableContent + Clone,
101{
102    fn clone(&self) -> Self {
103        Self {
104            content: self.content.clone(),
105            hash: self.hash.clone(),
106        }
107    }
108}
109
110impl<C> std::convert::From<HoloHashed<C>> for (C, HoloHashOf<C>)
111where
112    C: HashableContent,
113{
114    fn from(g: HoloHashed<C>) -> (C, HoloHashOf<C>) {
115        g.into_inner()
116    }
117}
118
119impl<C> std::ops::Deref for HoloHashed<C>
120where
121    C: HashableContent,
122{
123    type Target = C;
124
125    fn deref(&self) -> &Self::Target {
126        self.as_content()
127    }
128}
129
130impl<C> std::convert::AsRef<C> for HoloHashed<C>
131where
132    C: HashableContent,
133{
134    fn as_ref(&self) -> &C {
135        self.as_content()
136    }
137}
138
139impl<C> std::borrow::Borrow<C> for HoloHashed<C>
140where
141    C: HashableContent,
142{
143    fn borrow(&self) -> &C {
144        self.as_content()
145    }
146}
147
148impl<C> std::cmp::PartialEq for HoloHashed<C>
149where
150    C: HashableContent,
151{
152    fn eq(&self, other: &Self) -> bool {
153        self.hash == other.hash
154    }
155}
156
157impl<C> std::cmp::Eq for HoloHashed<C> where C: HashableContent {}
158
159impl<C> std::hash::Hash for HoloHashed<C>
160where
161    C: HashableContent,
162{
163    fn hash<StdH: std::hash::Hasher>(&self, state: &mut StdH) {
164        std::hash::Hash::hash(&self.hash, state)
165    }
166}
167
168impl<C> std::cmp::PartialOrd for HoloHashed<C>
169where
170    C: HashableContent + PartialOrd,
171{
172    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
173        self.content.partial_cmp(&other.content)
174    }
175}
176
177impl<C> std::cmp::Ord for HoloHashed<C>
178where
179    C: HashableContent + Ord,
180{
181    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
182        self.content.cmp(&other.content)
183    }
184}
185
186impl<C: HashableContent> HashableContent for HoloHashed<C> {
187    type HashType = C::HashType;
188
189    fn hash_type(&self) -> Self::HashType {
190        C::hash_type(self)
191    }
192
193    fn hashable_content(&self) -> crate::HashableContentBytes {
194        crate::HashableContentBytes::Prehashed39(self.as_hash().get_raw_39().to_vec())
195    }
196}