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