1use crate::HashType;
4use crate::HoloHash;
5use holochain_serialized_bytes::SerializedBytes;
6use holochain_serialized_bytes::SerializedBytesError;
7use holochain_serialized_bytes::UnsafeBytes;
8
9impl<T: HashType> serde::Serialize for HoloHash<T> {
10 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
11 where
12 S: serde::Serializer,
13 {
14 serializer.serialize_bytes(self.get_raw_39())
15 }
16}
17
18impl<'de, T: HashType> serde::Deserialize<'de> for HoloHash<T> {
19 fn deserialize<D>(deserializer: D) -> Result<HoloHash<T>, D::Error>
20 where
21 D: serde::Deserializer<'de>,
22 {
23 deserializer.deserialize_bytes(HoloHashVisitor(std::marker::PhantomData))
24 }
25}
26
27struct HoloHashVisitor<T: HashType>(std::marker::PhantomData<T>);
28
29impl<'de, T: HashType> serde::de::Visitor<'de> for HoloHashVisitor<T> {
30 type Value = HoloHash<T>;
31
32 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
33 formatter.write_str("a HoloHash of primitive hash_type")
34 }
35
36 fn visit_bytes<E>(self, h: &[u8]) -> Result<Self::Value, E>
37 where
38 E: serde::de::Error,
39 {
40 if !h.len() == 39 {
41 Err(serde::de::Error::custom(
42 "HoloHash serialized representation must be exactly 39 bytes",
43 ))
44 } else {
45 HoloHash::try_from_raw_39(h.to_vec())
46 .map_err(|e| serde::de::Error::custom(format!("HoloHash error: {:?}", e)))
47 }
48 }
49
50 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
51 where
52 A: serde::de::SeqAccess<'de>,
53 {
54 let mut vec = Vec::with_capacity(seq.size_hint().unwrap_or(0));
55
56 while let Some(b) = seq.next_element()? {
57 vec.push(b);
58 }
59
60 self.visit_bytes(&vec)
61 }
62
63 #[cfg(feature = "encoding")]
64 fn visit_str<E>(self, b64: &str) -> Result<Self::Value, E>
65 where
66 E: serde::de::Error,
67 {
68 let h = crate::holo_hash_decode_unchecked(b64)
69 .map_err(|e| serde::de::Error::custom(format!("HoloHash error: {:?}", e)))?;
70 if !h.len() == 39 {
71 Err(serde::de::Error::custom(
72 "HoloHash serialized representation must be exactly 39 bytes",
73 ))
74 } else {
75 HoloHash::try_from_raw_39(h.to_vec())
76 .map_err(|e| serde::de::Error::custom(format!("HoloHash error: {:?}", e)))
77 }
78 }
79}
80
81impl<T: HashType> std::convert::TryFrom<&HoloHash<T>> for SerializedBytes {
82 type Error = SerializedBytesError;
83 fn try_from(t: &HoloHash<T>) -> std::result::Result<SerializedBytes, SerializedBytesError> {
84 match holochain_serialized_bytes::encode(t) {
85 Ok(v) => Ok(SerializedBytes::from(UnsafeBytes::from(v))),
86 Err(e) => Err(SerializedBytesError::Serialize(e.to_string())),
87 }
88 }
89}
90
91impl<T: HashType> std::convert::TryFrom<HoloHash<T>> for SerializedBytes {
92 type Error = SerializedBytesError;
93 fn try_from(t: HoloHash<T>) -> std::result::Result<SerializedBytes, SerializedBytesError> {
94 SerializedBytes::try_from(&t)
95 }
96}
97
98impl<T: HashType> std::convert::TryFrom<SerializedBytes> for HoloHash<T> {
99 type Error = SerializedBytesError;
100 fn try_from(sb: SerializedBytes) -> std::result::Result<HoloHash<T>, SerializedBytesError> {
101 match holochain_serialized_bytes::decode(sb.bytes()) {
102 Ok(v) => Ok(v),
103 Err(e) => Err(SerializedBytesError::Deserialize(e.to_string())),
104 }
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use crate::*;
111 use holochain_serialized_bytes::prelude::*;
112 use std::convert::TryInto;
113
114 #[derive(serde::Deserialize, Debug)]
115 #[serde(transparent)]
116 struct TestByteArray(#[serde(with = "serde_bytes")] Vec<u8>);
117
118 #[test]
119 #[cfg(feature = "serialization")]
120 fn test_serialized_bytes_roundtrip() {
121 use holochain_serialized_bytes::SerializedBytes;
122 use std::convert::TryInto;
123
124 let h_orig = DnaHash::from_raw_36(vec![0xdb; HOLO_HASH_UNTYPED_LEN]);
125 let h: SerializedBytes = h_orig.clone().try_into().unwrap();
126 let h: DnaHash = h.try_into().unwrap();
127
128 assert_eq!(h_orig, h);
129 assert_eq!(*h.hash_type(), hash_type::Dna::new());
130 }
131
132 #[test]
133 fn test_rmp_roundtrip() {
134 let h_orig = AgentPubKey::from_raw_36(vec![0xdb; HOLO_HASH_UNTYPED_LEN]);
135 let buf = holochain_serialized_bytes::encode(&h_orig).unwrap();
136 let h: AgentPubKey = holochain_serialized_bytes::decode(&buf).unwrap();
137
138 assert_eq!(h_orig, h);
139 assert_eq!(*h.hash_type(), hash_type::Agent::new());
140
141 let array: TestByteArray = holochain_serialized_bytes::decode(&buf).unwrap();
143 assert_eq!(array.0.len(), HOLO_HASH_FULL_LEN);
144 assert_eq!(
145 array.0,
146 vec![
147 132, 32, 36, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
148 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
149 219, 219, 219, 219, 219, 219,
150 ]
151 );
152 }
153
154 #[test]
155 fn test_json_roundtrip() {
156 let h_orig = AgentPubKey::from_raw_36(vec![0xdb; HOLO_HASH_UNTYPED_LEN]);
157 let json = serde_json::to_string(&h_orig).unwrap();
158 let h: AgentPubKey = serde_json::from_str(&json).unwrap();
159
160 assert_eq!(h_orig, h);
161 assert_eq!(*h.hash_type(), hash_type::Agent::new());
162
163 let array: TestByteArray = serde_json::from_str(&json).unwrap();
165 assert_eq!(array.0.len(), HOLO_HASH_FULL_LEN);
166 assert_eq!(
167 array.0,
168 vec![
169 132, 32, 36, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
170 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
171 219, 219, 219, 219, 219, 219,
172 ]
173 );
174 }
175
176 #[test]
177 fn test_composite_hashtype_roundtrips() {
178 {
179 let h_orig = AnyDhtHash::from_raw_36_and_type(
180 vec![0xdb; HOLO_HASH_UNTYPED_LEN],
181 hash_type::AnyDht::Action,
182 );
183 let buf = holochain_serialized_bytes::encode(&h_orig).unwrap();
184 let h: AnyDhtHash = holochain_serialized_bytes::decode(&buf).unwrap();
185 assert_eq!(h_orig, h);
186 assert_eq!(*h.hash_type(), hash_type::AnyDht::Action);
187 }
188 {
189 let h_orig = AnyDhtHash::from_raw_36_and_type(
190 vec![0xdb; HOLO_HASH_UNTYPED_LEN],
191 hash_type::AnyDht::Entry,
192 );
193 let buf = holochain_serialized_bytes::encode(&h_orig).unwrap();
194 let h: AnyDhtHash = holochain_serialized_bytes::decode(&buf).unwrap();
195 assert_eq!(h_orig, h);
196 assert_eq!(*h.hash_type(), hash_type::AnyDht::Entry);
197 }
198 {
199 let h_orig = AnyDhtHash::from_raw_36_and_type(
200 vec![0xdb; HOLO_HASH_UNTYPED_LEN],
201 hash_type::AnyDht::Entry,
202 );
203 let buf = holochain_serialized_bytes::encode(&h_orig).unwrap();
204 let h: AnyDhtHash = holochain_serialized_bytes::decode(&buf).unwrap();
205 assert_eq!(h_orig, h);
206 assert_eq!(*h.hash_type(), hash_type::AnyDht::Entry);
207 }
208 }
209
210 #[test]
211 fn test_any_dht_deserialization() {
212 {
213 let h_orig = EntryHash::from_raw_36_and_type(
214 vec![0xdb; HOLO_HASH_UNTYPED_LEN],
215 hash_type::Entry,
216 );
217 let buf = holochain_serialized_bytes::encode(&h_orig).unwrap();
218 let _: AnyDhtHash = holochain_serialized_bytes::decode(&buf).unwrap();
219 }
220 {
221 let h_orig = ActionHash::from_raw_36_and_type(
222 vec![0xdb; HOLO_HASH_UNTYPED_LEN],
223 hash_type::Action,
224 );
225 let buf = holochain_serialized_bytes::encode(&h_orig).unwrap();
226 let _: AnyDhtHash = holochain_serialized_bytes::decode(&buf).unwrap();
227 }
228 }
229
230 #[test]
231 #[should_panic]
232 fn test_any_dht_deserialization_crossover_error() {
233 {
234 let h_orig = DhtOpHash::from_raw_36_and_type(
235 vec![0xdb; HOLO_HASH_UNTYPED_LEN],
236 hash_type::DhtOp,
237 );
238 let buf = holochain_serialized_bytes::encode(&h_orig).unwrap();
239 let _: AnyDhtHash = holochain_serialized_bytes::decode(&buf).unwrap();
240 }
241 }
242
243 #[test]
244 fn test_struct_to_struct_roundtrip() {
245 #[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, SerializedBytes)]
246 struct TestData {
247 e: EntryHash,
248 h: ActionHash,
249 }
250
251 let orig = TestData {
252 e: EntryHash::from_raw_36_and_type(vec![0xdb; HOLO_HASH_UNTYPED_LEN], hash_type::Entry),
253 h: ActionHash::from_raw_36(vec![0xdb; HOLO_HASH_UNTYPED_LEN]),
254 };
255
256 let sb: SerializedBytes = (&orig).try_into().unwrap();
257 let res: TestData = sb.try_into().unwrap();
258
259 assert_eq!(orig, res);
260 assert_eq!(*orig.e.hash_type(), hash_type::Entry);
261 assert_eq!(*orig.h.hash_type(), hash_type::Action);
262 }
263
264 #[test]
265 fn test_json_to_rust() {
266 #[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, SerializedBytes)]
267 struct Data {
268 any_hash: AnyDhtHash,
269 content: String,
270 }
271
272 let any_hash = AnyDhtHash::from_raw_36_and_type(
273 b"000000000000000000000000000000000000".to_vec(),
274 hash_type::AnyDht::Action,
275 );
276 let hash_type_sb: SerializedBytes = any_hash.hash_type().try_into().unwrap();
277 let hash_type_json = r#"{"Action":[132,41,36]}"#;
278 assert_eq!(format!("{:?}", hash_type_sb), hash_type_json.to_string());
279
280 let hash_type_from_sb: hash_type::AnyDht = hash_type_sb.try_into().unwrap();
281 assert_eq!(hash_type_from_sb, hash_type::AnyDht::Action);
282
283 let hash_type_from_json: hash_type::AnyDht = serde_json::from_str(hash_type_json).unwrap();
284 assert_eq!(hash_type_from_json, hash_type::AnyDht::Action);
285 }
286
287 #[test]
288 fn test_generic_content_roundtrip() {
289 #[derive(Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
290 struct Generic<K> {
291 bytes: Vec<u8>,
292 __marker: std::marker::PhantomData<K>,
293 }
294
295 impl<K> Generic<K>
296 where
297 K: serde::Serialize + serde::de::DeserializeOwned + std::fmt::Debug,
298 {
300 fn new() -> Self {
301 Self {
302 bytes: Vec::new(),
303 __marker: Default::default(),
304 }
305 }
306
307 fn get(&self) -> K {
308 holochain_serialized_bytes::decode(&self.bytes).unwrap()
309 }
310
311 fn put(&mut self, k: &K) {
312 self.bytes = holochain_serialized_bytes::encode(k).unwrap();
313 }
314 }
315
316 let mut g: Generic<ActionHash> = Generic::new();
317 let h = ActionHash::from_raw_36(vec![0xdb; HOLO_HASH_UNTYPED_LEN]);
318 g.put(&h);
319 assert_eq!(h, g.get());
320 }
321}