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#[cfg_attr(feature = "serialization", derive(Debug, Serialize, Deserialize))]
16pub struct HoloHashed<C: HashableContent> {
17 pub content: C,
19 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 pub fn with_pre_hashed(content: C, hash: HoloHashOf<C>) -> Self {
54 Self { content, hash }
55 }
56
57 pub fn as_content(&self) -> &C {
61 &self.content
62 }
63
64 #[cfg(feature = "test_utils")]
68 pub fn as_content_mut(&mut self) -> &mut C {
69 &mut self.content
70 }
71
72 pub fn into_content(self) -> C {
74 self.content
75 }
76
77 pub fn into_inner(self) -> (C, HoloHashOf<C>) {
79 (self.content, self.hash)
80 }
81
82 #[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}