1use std::fmt;
4use std::marker::PhantomData;
5
6use serde::de::{Error as SerdeError, SeqAccess, Visitor};
7use serde::ser::SerializeSeq;
8use serde::{Deserialize, Serialize};
9use serde_bytes::{ByteBuf as SerdeByteBuf, Bytes as SerdeBytes};
10
11use crate::hash::{Hash, HashError};
12use crate::identity::{IdentityError, PrivateKey, PublicKey, Signature};
13use crate::operation::{Body, Header};
14
15pub fn serialize_hex<S>(value: &[u8], serializer: S) -> Result<S::Ok, S::Error>
18where
19 S: serde::Serializer,
20{
21 if serializer.is_human_readable() {
22 hex::serde::serialize(value, serializer)
23 } else {
24 SerdeBytes::new(value).serialize(serializer)
25 }
26}
27
28pub fn deserialize_hex<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
31where
32 D: serde::Deserializer<'de>,
33{
34 if deserializer.is_human_readable() {
35 hex::serde::deserialize(deserializer)
36 } else {
37 let bytes = <SerdeByteBuf>::deserialize(deserializer)?;
38 Ok(bytes.to_vec())
39 }
40}
41
42impl Serialize for Hash {
43 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
44 where
45 S: serde::Serializer,
46 {
47 serialize_hex(self.as_bytes(), serializer)
48 }
49}
50
51impl<'de> Deserialize<'de> for Hash {
52 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
53 where
54 D: serde::Deserializer<'de>,
55 {
56 let bytes = deserialize_hex(deserializer)?;
57
58 bytes
59 .as_slice()
60 .try_into()
61 .map_err(|err: HashError| serde::de::Error::custom(err.to_string()))
62 }
63}
64
65impl Serialize for PrivateKey {
66 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
67 where
68 S: serde::Serializer,
69 {
70 serialize_hex(self.as_bytes(), serializer)
71 }
72}
73
74impl<'de> Deserialize<'de> for PrivateKey {
75 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
76 where
77 D: serde::Deserializer<'de>,
78 {
79 let bytes = deserialize_hex(deserializer)?;
80
81 bytes
82 .as_slice()
83 .try_into()
84 .map_err(|err: IdentityError| serde::de::Error::custom(err.to_string()))
85 }
86}
87
88impl Serialize for PublicKey {
89 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
90 where
91 S: serde::Serializer,
92 {
93 serialize_hex(self.as_bytes(), serializer)
94 }
95}
96
97impl<'de> Deserialize<'de> for PublicKey {
98 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
99 where
100 D: serde::Deserializer<'de>,
101 {
102 let bytes = deserialize_hex(deserializer)?;
103
104 bytes
105 .as_slice()
106 .try_into()
107 .map_err(|err: IdentityError| serde::de::Error::custom(err.to_string()))
108 }
109}
110
111impl Serialize for Signature {
112 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
113 where
114 S: serde::Serializer,
115 {
116 serialize_hex(&self.to_bytes(), serializer)
117 }
118}
119
120impl<'de> Deserialize<'de> for Signature {
121 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
122 where
123 D: serde::Deserializer<'de>,
124 {
125 let bytes = deserialize_hex(deserializer)?;
126
127 bytes
128 .as_slice()
129 .try_into()
130 .map_err(|err: IdentityError| serde::de::Error::custom(err.to_string()))
131 }
132}
133
134impl<E> Serialize for Header<E>
135where
136 E: Serialize,
137{
138 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
139 where
140 S: serde::Serializer,
141 {
142 let mut seq = serializer.serialize_seq(Some(self.field_count()))?;
143 seq.serialize_element(&self.version)?;
144 seq.serialize_element(&self.public_key)?;
145
146 if let Some(signature) = &self.signature {
147 seq.serialize_element(signature)?;
148 }
149
150 seq.serialize_element(&self.payload_size)?;
151 if let Some(hash) = &self.payload_hash {
152 seq.serialize_element(&hash)?;
153 }
154
155 seq.serialize_element(&self.timestamp)?;
156 seq.serialize_element(&self.seq_num)?;
157
158 if let Some(backlink) = &self.backlink {
159 seq.serialize_element(backlink)?;
160 }
161
162 seq.serialize_element(&self.previous)?;
163
164 seq.serialize_element(&self.extensions)?;
167
168 seq.end()
169 }
170}
171
172impl<'de, E> Deserialize<'de> for Header<E>
173where
174 E: Deserialize<'de>,
175{
176 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
177 where
178 D: serde::Deserializer<'de>,
179 {
180 struct HeaderVisitor<E> {
181 _marker: PhantomData<E>,
182 }
183
184 impl<'de, E> Visitor<'de> for HeaderVisitor<E>
185 where
186 E: Deserialize<'de>,
187 {
188 type Value = Header<E>;
189
190 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
191 formatter.write_str("Header encoded as a sequence")
192 }
193
194 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
195 where
196 A: SeqAccess<'de>,
197 {
198 let version: u64 = seq
199 .next_element()?
200 .ok_or(SerdeError::custom("version missing"))?;
201
202 let public_key: PublicKey = seq
203 .next_element()?
204 .ok_or(SerdeError::custom("public key missing"))?;
205
206 let signature: Signature = seq
207 .next_element()?
208 .ok_or(SerdeError::custom("signature missing"))?;
209
210 let payload_size: u64 = seq
211 .next_element()?
212 .ok_or(SerdeError::custom("payload size missing"))?;
213
214 let payload_hash: Option<Hash> = match payload_size {
215 0 => None,
216 _ => {
217 let hash: Hash = seq
218 .next_element()?
219 .ok_or(SerdeError::custom("payload hash missing"))?;
220 Some(hash)
221 }
222 };
223
224 let timestamp: u64 = seq
225 .next_element()?
226 .ok_or(SerdeError::custom("timestamp missing"))?;
227
228 let seq_num: u64 = seq
229 .next_element()?
230 .ok_or(SerdeError::custom("sequence number missing"))?;
231
232 let backlink: Option<Hash> = match seq_num {
233 0 => None,
234 _ => {
235 let hash: Hash = seq
236 .next_element()?
237 .ok_or(SerdeError::custom("backlink missing"))?;
238 Some(hash)
239 }
240 };
241
242 let previous: Vec<Hash> = seq
243 .next_element()?
244 .ok_or(SerdeError::custom("previous array missing"))?;
245
246 let extensions: E = seq
249 .next_element()?
250 .ok_or(SerdeError::custom("extensions missing"))?;
251
252 Ok(Header {
253 version,
254 public_key,
255 signature: Some(signature),
256 payload_hash,
257 payload_size,
258 timestamp,
259 seq_num,
260 backlink,
261 previous,
262 extensions,
263 })
264 }
265 }
266
267 deserializer.deserialize_seq(HeaderVisitor::<E> {
268 _marker: PhantomData,
269 })
270 }
271}
272
273impl Serialize for Body {
274 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
275 where
276 S: serde::Serializer,
277 {
278 serialize_hex(&self.0, serializer)
279 }
280}
281
282impl<'de> Deserialize<'de> for Body {
283 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
284 where
285 D: serde::Deserializer<'de>,
286 {
287 let bytes = deserialize_hex(deserializer)?;
288 Ok(Body(bytes.to_vec()))
289 }
290}
291
292#[cfg(test)]
293mod tests {
294 use serde::de::DeserializeOwned;
295 use serde::{Deserialize, Serialize};
296
297 use crate::Body;
298 use crate::hash::Hash;
299 use crate::identity::{PrivateKey, PublicKey};
300 use crate::operation::Header;
301
302 use super::{deserialize_hex, serialize_hex};
303
304 #[derive(Debug, Serialize, Deserialize)]
305 struct Test(
306 #[serde(serialize_with = "serialize_hex", deserialize_with = "deserialize_hex")] Vec<u8>,
307 );
308
309 #[test]
310 fn serialize() {
311 let mut bytes: Vec<u8> = Vec::new();
312 let test = Test(vec![1, 2, 3]);
313
314 ciborium::ser::into_writer(&test, &mut bytes).unwrap();
317 assert_eq!(vec![67, 1, 2, 3], bytes);
318 }
319
320 #[test]
321 fn deserialize() {
322 let bytes: Vec<u8> = vec![67, 1, 2, 3];
323
324 let test: Test = ciborium::de::from_reader(&bytes[..]).unwrap();
327 assert_eq!(test.0, vec![1, 2, 3]);
328 }
329
330 #[test]
331 fn serialize_hash() {
332 let mut bytes: Vec<u8> = Vec::new();
334 let hash = Hash::new([1, 2, 3]);
335 ciborium::ser::into_writer(&hash, &mut bytes).unwrap();
336 assert_eq!(
337 bytes,
338 vec![
339 88, 32, 177, 119, 236, 27, 242, 109, 251, 59, 112, 16, 212, 115, 230, 212, 71, 19,
340 178, 155, 118, 91, 153, 198, 230, 14, 203, 250, 231, 66, 222, 73, 101, 67
341 ]
342 );
343
344 let json = serde_json::to_string(&hash).unwrap();
346 assert_eq!(
347 json,
348 "\"b177ec1bf26dfb3b7010d473e6d44713b29b765b99c6e60ecbfae742de496543\""
349 );
350 }
351
352 #[test]
353 fn deserialize_hash() {
354 let bytes = [
356 88, 32, 177, 119, 236, 27, 242, 109, 251, 59, 112, 16, 212, 115, 230, 212, 71, 19, 178,
357 155, 118, 91, 153, 198, 230, 14, 203, 250, 231, 66, 222, 73, 101, 67,
358 ];
359 let hash: Hash = ciborium::de::from_reader(&bytes[..]).unwrap();
360 assert_eq!(hash, Hash::new([1, 2, 3]));
361
362 let json = "\"b177ec1bf26dfb3b7010d473e6d44713b29b765b99c6e60ecbfae742de496543\"";
364 let hash: Hash = serde_json::from_str(json).unwrap();
365 assert_eq!(hash, Hash::new([1, 2, 3]));
366 }
367
368 #[test]
369 fn serialize_public_key() {
370 let mut bytes: Vec<u8> = Vec::new();
372 let public_key = PublicKey::from_bytes(&[
373 215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58, 14, 225, 114,
374 243, 218, 166, 35, 37, 175, 2, 26, 104, 247, 7, 81, 26,
375 ])
376 .unwrap();
377 ciborium::ser::into_writer(&public_key, &mut bytes).unwrap();
378 assert_eq!(
379 bytes,
380 vec![
381 88, 32, 215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58, 14,
382 225, 114, 243, 218, 166, 35, 37, 175, 2, 26, 104, 247, 7, 81, 26,
383 ]
384 );
385
386 let json = serde_json::to_string(&public_key).unwrap();
388 assert_eq!(
389 json,
390 "\"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a\""
391 );
392 }
393
394 fn assert_serde_roundtrip<
395 E: Clone + std::fmt::Debug + PartialEq + Serialize + DeserializeOwned,
396 >(
397 mut header: Header<E>,
398 private_key: &PrivateKey,
399 ) {
400 header.sign(private_key);
401
402 let mut bytes = Vec::new();
403 ciborium::ser::into_writer(&header, &mut bytes).unwrap();
404 let header_again: Header<E> = ciborium::de::from_reader(&bytes[..]).unwrap();
405 assert_eq!(header, header_again);
406 }
407
408 #[test]
409 fn serde_roundtrip_operations() {
410 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
411 struct CustomExtensions {
412 custom_field: u64,
413 }
414
415 let extensions = CustomExtensions { custom_field: 12 };
416 let private_key = PrivateKey::new();
417
418 assert_serde_roundtrip(
419 Header::<CustomExtensions> {
420 version: 1,
421 public_key: private_key.public_key(),
422 payload_size: 123,
423 payload_hash: Some(Hash::new(vec![1, 2, 3])),
424 timestamp: 0,
425 seq_num: 0,
426 backlink: None,
427 previous: vec![],
428 extensions: extensions.clone(),
429 signature: None,
430 },
431 &private_key,
432 );
433
434 assert_serde_roundtrip(
435 Header::<CustomExtensions> {
436 version: 1,
437 public_key: private_key.public_key(),
438 payload_size: 0,
439 payload_hash: None,
440 timestamp: 0,
441 seq_num: 0,
442 backlink: None,
443 previous: vec![],
444 extensions: extensions,
445 signature: None,
446 },
447 &private_key,
448 );
449 }
450
451 #[test]
452 fn expected_de_error() {
453 let private_key = PrivateKey::new();
454
455 let mut header = Header::<()> {
457 version: 1,
458 public_key: private_key.public_key(),
459 signature: None,
460 payload_size: 2829099,
461 payload_hash: None,
462 timestamp: 0,
463 seq_num: 0,
464 backlink: None,
465 previous: vec![],
466 extensions: (),
467 };
468 header.sign(&private_key);
469
470 let result = ciborium::de::from_reader::<Header<()>, _>(&header.to_bytes()[..]);
471 assert!(result.is_err());
472
473 let mut header = Header::<()> {
475 version: 1,
476 public_key: private_key.public_key(),
477 signature: None,
478 payload_size: 0,
479 payload_hash: Some(Hash::new([0, 1, 2])),
480 timestamp: 0,
481 seq_num: 0,
482 backlink: None,
483 previous: vec![],
484 extensions: (),
485 };
486 header.sign(&private_key);
487
488 let result = ciborium::de::from_reader::<Header<()>, _>(&header.to_bytes()[..]);
489 assert!(result.is_err());
490
491 let mut header = Header::<()> {
493 version: 1,
494 public_key: private_key.public_key(),
495 signature: None,
496 payload_size: 0,
497 payload_hash: None,
498 timestamp: 0,
499 seq_num: 0,
500 backlink: Some(Hash::new([0, 1, 2])),
501 previous: vec![],
502 extensions: (),
503 };
504 header.sign(&private_key);
505
506 let result = ciborium::de::from_reader::<Header<()>, _>(&header.to_bytes()[..]);
507 assert!(result.is_err());
508
509 let mut header = Header::<()> {
511 version: 1,
512 public_key: private_key.public_key(),
513 signature: None,
514 payload_size: 0,
515 payload_hash: None,
516 timestamp: 0,
517 seq_num: 10,
518 backlink: None,
519 previous: vec![],
520 extensions: (),
521 };
522 header.sign(&private_key);
523
524 let result = ciborium::de::from_reader::<Header<()>, _>(&header.to_bytes()[..]);
525 assert!(result.is_err());
526 }
527
528 #[test]
529 fn serde_header_with_other_types() {
530 let private_key = PrivateKey::new();
531
532 #[derive(Debug, PartialEq, Serialize, Deserialize)]
533 struct Message {
534 header: Header<()>,
535 body: Body,
536 }
537
538 let body = Body::new(b"hello");
539 let mut header = Header::<()> {
540 version: 1,
541 public_key: private_key.public_key(),
542 signature: None,
543 payload_size: body.size(),
544 payload_hash: Some(body.hash()),
545 timestamp: 0,
546 seq_num: 0,
547 backlink: None,
548 previous: vec![],
549 extensions: (),
550 };
551 header.sign(&private_key);
552
553 let message = Message { header, body };
554
555 let mut bytes = Vec::new();
556 ciborium::ser::into_writer(&message, &mut bytes).unwrap();
557
558 let message_again: Message = ciborium::de::from_reader(&bytes[..]).unwrap();
559 assert_eq!(message_again, message);
560 }
561
562 #[test]
563 fn fixtures() {
564 let private_key = PrivateKey::from_bytes(&[
565 244, 123, 85, 215, 161, 204, 94, 227, 239, 253, 128, 164, 228, 160, 195, 49, 18, 49,
566 125, 4, 50, 218, 157, 230, 174, 1, 154, 231, 231, 142, 22, 170,
567 ]);
568
569 let mut header_0 = Header::<()> {
571 version: 1,
572 public_key: private_key.public_key(),
573 signature: None,
574 payload_size: 0,
575 payload_hash: None,
576 timestamp: 0,
577 seq_num: 0,
578 backlink: None,
579 previous: vec![],
580 extensions: (),
581 };
582 header_0.sign(&private_key);
583
584 let bytes = [
585 136, 1, 88, 32, 228, 21, 196, 25, 12, 199, 241, 100, 122, 89, 46, 191, 142, 95, 144,
586 92, 42, 222, 249, 148, 139, 23, 91, 43, 92, 17, 225, 69, 17, 181, 22, 32, 88, 64, 177,
587 60, 248, 186, 240, 172, 58, 52, 236, 91, 174, 35, 231, 179, 180, 2, 105, 53, 7, 78, 71,
588 179, 99, 159, 171, 47, 250, 15, 242, 228, 75, 39, 112, 204, 138, 63, 88, 171, 227, 239,
589 194, 88, 171, 32, 138, 26, 93, 203, 190, 178, 85, 186, 245, 227, 45, 65, 169, 195, 90,
590 212, 39, 49, 28, 0, 0, 0, 0, 128, 246,
591 ];
592
593 let header_again: Header<()> = ciborium::de::from_reader(&bytes[..]).unwrap();
594 assert_eq!(header_0, header_again);
595
596 let mut header_0_with_previous = Header::<()> {
598 version: 1,
599 public_key: private_key.public_key(),
600 signature: None,
601 payload_size: 0,
602 payload_hash: None,
603 timestamp: 0,
604 seq_num: 0,
605 backlink: None,
606 previous: vec![header_0.hash()],
607 extensions: (),
608 };
609 header_0_with_previous.sign(&private_key);
610
611 let bytes = [
612 136, 1, 88, 32, 228, 21, 196, 25, 12, 199, 241, 100, 122, 89, 46, 191, 142, 95, 144,
613 92, 42, 222, 249, 148, 139, 23, 91, 43, 92, 17, 225, 69, 17, 181, 22, 32, 88, 64, 86,
614 187, 206, 107, 141, 200, 7, 157, 107, 47, 49, 47, 4, 177, 76, 141, 51, 230, 245, 151,
615 124, 185, 157, 79, 59, 59, 14, 91, 105, 6, 229, 145, 62, 167, 203, 221, 253, 28, 128,
616 113, 59, 30, 148, 3, 153, 7, 16, 55, 52, 195, 216, 9, 97, 167, 205, 26, 141, 82, 229,
617 39, 124, 198, 186, 9, 0, 0, 0, 129, 88, 32, 201, 88, 182, 128, 125, 179, 108, 4, 23,
618 151, 168, 52, 216, 181, 123, 95, 11, 78, 75, 6, 236, 167, 141, 219, 243, 115, 255, 203,
619 100, 128, 30, 92, 246,
620 ];
621
622 let header_again: Header<()> = ciborium::de::from_reader(&bytes[..]).unwrap();
623 assert_eq!(header_0_with_previous, header_again);
624
625 let body = Body::new("Hello, Sloth!".as_bytes());
627 let mut header_0_with_previous_and_body = Header::<()> {
628 version: 1,
629 public_key: private_key.public_key(),
630 signature: None,
631 payload_size: body.size(),
632 payload_hash: Some(body.hash()),
633 timestamp: 0,
634 seq_num: 0,
635 backlink: None,
636 previous: vec![header_0.hash()],
637 extensions: (),
638 };
639 header_0_with_previous_and_body.sign(&private_key);
640
641 let bytes = [
642 137, 1, 88, 32, 228, 21, 196, 25, 12, 199, 241, 100, 122, 89, 46, 191, 142, 95, 144,
643 92, 42, 222, 249, 148, 139, 23, 91, 43, 92, 17, 225, 69, 17, 181, 22, 32, 88, 64, 152,
644 61, 237, 59, 97, 221, 165, 207, 164, 49, 55, 177, 168, 40, 36, 190, 47, 59, 86, 231,
645 231, 117, 182, 186, 45, 142, 7, 98, 17, 1, 153, 173, 165, 127, 208, 222, 173, 157, 81,
646 165, 228, 184, 230, 165, 88, 173, 41, 104, 171, 12, 18, 57, 179, 18, 254, 50, 65, 226,
647 147, 228, 201, 28, 123, 7, 13, 88, 32, 191, 127, 68, 13, 227, 43, 252, 155, 49, 148,
648 176, 2, 162, 217, 175, 171, 49, 44, 181, 215, 71, 113, 211, 195, 29, 128, 192, 169, 5,
649 138, 160, 142, 0, 0, 129, 88, 32, 201, 88, 182, 128, 125, 179, 108, 4, 23, 151, 168,
650 52, 216, 181, 123, 95, 11, 78, 75, 6, 236, 167, 141, 219, 243, 115, 255, 203, 100, 128,
651 30, 92, 246,
652 ];
653
654 let header_again: Header<()> = ciborium::de::from_reader(&bytes[..]).unwrap();
655 assert_eq!(header_0_with_previous_and_body, header_again);
656
657 let mut header_1 = Header::<()> {
659 version: 1,
660 public_key: private_key.public_key(),
661 signature: None,
662 payload_size: 0,
663 payload_hash: None,
664 timestamp: 0,
665 seq_num: 1,
666 backlink: Some(header_0.hash()),
667 previous: vec![],
668 extensions: (),
669 };
670 header_1.sign(&private_key);
671
672 let bytes = [
673 137, 1, 88, 32, 228, 21, 196, 25, 12, 199, 241, 100, 122, 89, 46, 191, 142, 95, 144,
674 92, 42, 222, 249, 148, 139, 23, 91, 43, 92, 17, 225, 69, 17, 181, 22, 32, 88, 64, 159,
675 29, 188, 12, 62, 68, 90, 135, 233, 157, 134, 251, 205, 180, 206, 144, 230, 240, 161,
676 42, 236, 217, 77, 210, 161, 229, 92, 67, 213, 170, 105, 53, 16, 57, 43, 62, 143, 162,
677 177, 91, 154, 154, 131, 45, 138, 152, 49, 80, 42, 144, 249, 30, 166, 143, 139, 255, 54,
678 65, 180, 15, 102, 222, 210, 6, 0, 0, 1, 88, 32, 201, 88, 182, 128, 125, 179, 108, 4,
679 23, 151, 168, 52, 216, 181, 123, 95, 11, 78, 75, 6, 236, 167, 141, 219, 243, 115, 255,
680 203, 100, 128, 30, 92, 128, 246,
681 ];
682
683 let header_again: Header<()> = ciborium::de::from_reader(&bytes[..]).unwrap();
684 assert_eq!(header_1, header_again);
685
686 let mut header_1_with_previous = Header::<()> {
688 version: 1,
689 public_key: private_key.public_key(),
690 signature: None,
691 payload_size: 0,
692 payload_hash: None,
693 timestamp: 0,
694 seq_num: 1,
695 backlink: Some(header_0.hash()),
696 previous: vec![header_0.hash()],
697 extensions: (),
698 };
699 header_1_with_previous.sign(&private_key);
700
701 let bytes = [
702 137, 1, 88, 32, 228, 21, 196, 25, 12, 199, 241, 100, 122, 89, 46, 191, 142, 95, 144,
703 92, 42, 222, 249, 148, 139, 23, 91, 43, 92, 17, 225, 69, 17, 181, 22, 32, 88, 64, 147,
704 144, 109, 231, 188, 44, 47, 38, 189, 192, 85, 151, 242, 49, 40, 30, 155, 198, 216, 52,
705 140, 216, 65, 66, 19, 227, 159, 175, 23, 107, 113, 180, 100, 44, 161, 228, 126, 219,
706 10, 85, 71, 59, 156, 117, 23, 1, 101, 224, 96, 75, 45, 25, 17, 37, 56, 78, 184, 120,
707 39, 115, 95, 127, 83, 3, 0, 0, 1, 88, 32, 201, 88, 182, 128, 125, 179, 108, 4, 23, 151,
708 168, 52, 216, 181, 123, 95, 11, 78, 75, 6, 236, 167, 141, 219, 243, 115, 255, 203, 100,
709 128, 30, 92, 129, 88, 32, 201, 88, 182, 128, 125, 179, 108, 4, 23, 151, 168, 52, 216,
710 181, 123, 95, 11, 78, 75, 6, 236, 167, 141, 219, 243, 115, 255, 203, 100, 128, 30, 92,
711 246,
712 ];
713
714 let header_again: Header<()> = ciborium::de::from_reader(&bytes[..]).unwrap();
715 assert_eq!(header_1_with_previous, header_again);
716 }
717
718 #[test]
719 fn decode_non_map_extensions() {
720 let private_key = PrivateKey::new();
721
722 let mut header = Header::<()> {
723 version: 1,
724 public_key: private_key.public_key(),
725 signature: None,
726 payload_size: 0,
727 payload_hash: None,
728 timestamp: 0,
729 seq_num: 0,
730 backlink: None,
731 previous: vec![],
732 extensions: (),
733 };
734 header.sign(&private_key);
735
736 let result = ciborium::de::from_reader::<Header<()>, _>(&header.to_bytes()[..]);
737 assert!(result.is_ok());
738 }
739
740 #[test]
741 fn unexpected_eof_when_incomplete() {
742 let incomplete = [
745 137, 1, 88, 32, 228, 21, 196, 25, 12, 199, 241, 100, 122, 89, 46, 191, 142, 95, 144,
746 ];
747
748 let result: Result<Header<()>, _> = ciborium::de::from_reader(&incomplete[..]);
749 assert!(matches!(result, Err(ciborium::de::Error::Io(_))));
750 }
751}