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