Skip to main content

holo_hash/
hashed.rs

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