1use super::TypeError;
4use crate::{value::Number, Cbor, CborOwned, Encoder, ItemKind, TaggedItem, Writer};
5use std::{
6 any::TypeId,
7 borrow::Cow,
8 collections::{BTreeMap, BTreeSet, HashMap, HashSet},
9 convert::TryInto,
10 error::Error,
11 hash::Hash,
12};
13
14#[cfg(feature = "derive")]
15pub use cbor_data_derive::{ReadCbor, WriteCbor};
16
17#[derive(Debug)]
18pub enum CodecError {
19 TypeError(TypeError),
20 WrongNumber(&'static str),
21 TupleSize {
22 expected: usize,
23 found: usize,
24 },
25 NoKnownVariant {
26 known: &'static [&'static str],
27 present: Vec<String>,
28 },
29 MissingField(&'static str),
30 Custom(Box<dyn Error + Send + Sync>),
31 String(String),
32 WithContext(String, Box<CodecError>),
33}
34
35impl PartialEq for CodecError {
36 fn eq(&self, other: &Self) -> bool {
37 match (self, other) {
38 (Self::TypeError(l0), Self::TypeError(r0)) => l0 == r0,
39 (
40 Self::TupleSize {
41 expected: l_expected,
42 found: l_found,
43 },
44 Self::TupleSize {
45 expected: r_expected,
46 found: r_found,
47 },
48 ) => l_expected == r_expected && l_found == r_found,
49 (Self::WrongNumber(l0), Self::WrongNumber(r0)) => l0 == r0,
50 (
51 Self::NoKnownVariant {
52 known: l_known,
53 present: l_present,
54 },
55 Self::NoKnownVariant {
56 known: r_known,
57 present: r_present,
58 },
59 ) => l_known == r_known && l_present == r_present,
60 (Self::MissingField(l0), Self::MissingField(r0)) => l0 == r0,
61 (Self::Custom(l0), Self::Custom(r0)) => l0.to_string() == r0.to_string(),
62 (Self::String(l0), Self::String(r0)) => l0 == r0,
63 (Self::WithContext(l0, l1), Self::WithContext(r0, r1)) => l0 == r0 && l1 == r1,
64 _ => false,
65 }
66 }
67}
68
69impl CodecError {
70 pub fn type_error(target: &'static str, item: &TaggedItem<'_>) -> Self {
71 Self::TypeError(TypeError {
72 target,
73 kind: item.kind().into(),
74 tags: item.tags().into(),
75 })
76 }
77
78 pub fn tuple_size(expected: usize, found: usize) -> Self {
79 Self::TupleSize { expected, found }
80 }
81
82 pub fn custom(err: impl Error + Send + Sync + 'static) -> Self {
83 Self::Custom(Box::new(err))
84 }
85
86 pub fn str(err: impl Into<String>) -> Self {
87 Self::String(err.into())
88 }
89
90 pub fn with_ctx(self, f: impl FnOnce(&mut String)) -> Self {
91 match self {
92 Self::WithContext(mut ctx, err) => {
93 ctx.push_str(" <- ");
94 f(&mut ctx);
95 Self::WithContext(ctx, err)
96 }
97 err => {
98 let mut ctx = String::new();
99 f(&mut ctx);
100 Self::WithContext(ctx, Box::new(err))
101 }
102 }
103 }
104}
105
106impl std::fmt::Display for CodecError {
107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108 match self {
109 CodecError::TypeError(e) => write!(f, "{}", e),
110 CodecError::WrongNumber(s) => write!(f, "wrong number format (found {})", s),
111 CodecError::TupleSize { expected, found } => write!(
112 f,
113 "wrong tuple size: expected {}, found {}",
114 expected, found
115 ),
116 CodecError::NoKnownVariant { known, present } => {
117 write!(f, "unknown variant: known [")?;
118 for (idx, k) in known.iter().enumerate() {
119 if idx > 0 {
120 write!(f, ", ")?;
121 }
122 write!(f, "{}", k)?;
123 }
124 write!(f, "], present [")?;
125 for (idx, p) in present.iter().enumerate() {
126 if idx > 0 {
127 write!(f, ", ")?;
128 }
129 write!(f, "{}", p)?;
130 }
131 write!(f, "]")?;
132 Ok(())
133 }
134 CodecError::MissingField(name) => write!(f, "missing field `{}`", name),
135 CodecError::Custom(err) => write!(f, "codec error: {}", err),
136 CodecError::String(err) => write!(f, "codec error: {}", err),
137 CodecError::WithContext(ctx, err) => write!(f, "error decoding {}: {}", ctx, err),
138 }
139 }
140}
141impl Error for CodecError {}
142
143impl From<TypeError> for CodecError {
144 fn from(te: TypeError) -> Self {
145 Self::TypeError(te)
146 }
147}
148
149pub type Result<T> = std::result::Result<T, CodecError>;
150
151pub trait WriteCbor {
152 fn write_cbor<W: Writer>(&self, w: W) -> W::Output;
153}
154
155pub trait ReadCbor {
156 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result;
157
158 fn name() -> String {
159 let mut s = String::new();
160 Self::fmt(&mut s).unwrap();
161 s
162 }
163
164 fn read_cbor(cbor: &Cbor) -> Result<Self>
165 where
166 Self: Sized,
167 {
168 Self::read_cbor_impl(cbor).map_err(|err| {
169 err.with_ctx(|ctx| {
170 Self::fmt(ctx).ok();
171 })
172 })
173 }
174
175 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
176 where
177 Self: Sized;
178}
179
180pub trait ReadCborBorrowed<'a>: ToOwned + 'a {
181 fn read_cbor_borrowed(cbor: &'a Cbor) -> Result<Cow<'a, Self>>;
182}
183
184impl<T: WriteCbor> WriteCbor for Vec<T> {
185 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
186 w.encode_array(|mut b| {
187 for item in self {
188 item.write_cbor(&mut b);
189 }
190 })
191 }
192}
193
194impl<T: WriteCbor> WriteCbor for [T] {
195 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
196 w.encode_array(|mut w| {
197 for item in self {
198 item.write_cbor(&mut w);
199 }
200 })
201 }
202}
203
204impl<T: ReadCbor> ReadCbor for Vec<T> {
205 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
206 write!(f, "Vec<")?;
207 T::fmt(f)?;
208 write!(f, ">")?;
209 Ok(())
210 }
211
212 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
213 where
214 Self: Sized,
215 {
216 let a = cbor.try_array()?;
217 let mut v = Vec::with_capacity(a.len());
218 for item in a {
219 v.push(T::read_cbor(item.as_ref())?);
220 }
221 Ok(v)
222 }
223}
224
225#[repr(transparent)]
226pub struct AsByteString<T>(pub T);
227
228impl<T: AsRef<[u8]>> WriteCbor for AsByteString<T> {
229 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
230 w.encode_bytes(self.0.as_ref())
231 }
232}
233
234impl<'a> ReadCborBorrowed<'a> for [u8] {
235 fn read_cbor_borrowed(cbor: &'a Cbor) -> Result<Cow<'a, Self>> {
236 cbor.try_bytes().map_err(Into::into)
237 }
238}
239
240impl<T: for<'a> From<&'a [u8]> + 'static> ReadCbor for AsByteString<T> {
241 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
242 write!(f, "AsByteString({:?})", TypeId::of::<T>())
243 }
244
245 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
246 where
247 Self: Sized,
248 {
249 Ok(AsByteString(T::from(
250 <[u8]>::read_cbor_borrowed(cbor)?.as_ref(),
251 )))
252 }
253}
254
255impl<'a, T: ToOwned + WriteCbor> WriteCbor for Cow<'a, T> {
256 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
257 self.as_ref().write_cbor(w)
258 }
259}
260
261impl<'a, T: ToOwned> ReadCbor for Cow<'a, T>
262where
263 T::Owned: ReadCbor,
264{
265 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
266 write!(f, "Cow<")?;
267 T::Owned::fmt(f)?;
268 write!(f, ">")?;
269 Ok(())
270 }
271
272 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
273 where
274 Self: Sized,
275 {
276 Ok(Cow::Owned(ReadCbor::read_cbor(cbor)?))
277 }
278}
279
280impl WriteCbor for String {
281 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
282 w.encode_str(self)
283 }
284}
285
286impl<'a> WriteCbor for &'a str {
287 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
288 w.encode_str(self)
289 }
290}
291
292impl<'a> ReadCborBorrowed<'a> for str {
293 fn read_cbor_borrowed(cbor: &'a Cbor) -> Result<Cow<'a, Self>> {
294 cbor.try_str().map_err(Into::into)
295 }
296}
297
298impl ReadCbor for String {
299 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
300 write!(f, "String")
301 }
302
303 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
304 where
305 Self: Sized,
306 {
307 Ok(str::read_cbor_borrowed(cbor)?.into_owned())
308 }
309}
310
311impl<T: WriteCbor> WriteCbor for Option<T> {
312 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
313 if let Some(this) = self {
314 this.write_cbor(w)
315 } else {
316 w.encode_null()
317 }
318 }
319}
320
321impl<T: ReadCbor> ReadCbor for Option<T> {
322 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
323 where
324 Self: Sized,
325 {
326 if let ItemKind::Null = cbor.tagged_item().kind() {
327 Ok(None)
328 } else {
329 Ok(Some(T::read_cbor(cbor)?))
330 }
331 }
332
333 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
334 write!(f, "Option<")?;
335 T::fmt(f)?;
336 write!(f, ">")?;
337 Ok(())
338 }
339}
340
341impl<K: WriteCbor, V: WriteCbor> WriteCbor for BTreeMap<K, V> {
342 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
343 w.encode_dict(|w| {
344 for (k, v) in self {
345 w.with_cbor_key(|w| k.write_cbor(w), |w| v.write_cbor(w));
346 }
347 })
348 }
349}
350
351impl<K: ReadCbor + Ord, V: ReadCbor> ReadCbor for BTreeMap<K, V> {
352 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
353 where
354 Self: Sized,
355 {
356 let mut map = BTreeMap::new();
357 for (k, v) in cbor.try_dict()? {
358 map.insert(K::read_cbor(k.as_ref())?, V::read_cbor(v.as_ref())?);
359 }
360 Ok(map)
361 }
362
363 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
364 write!(f, "BTreeMap<")?;
365 K::fmt(f)?;
366 write!(f, ", ")?;
367 V::fmt(f)?;
368 write!(f, ">")?;
369 Ok(())
370 }
371}
372
373impl<K: WriteCbor, V: WriteCbor> WriteCbor for HashMap<K, V> {
374 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
375 w.encode_dict(|w| {
376 for (k, v) in self {
377 w.with_cbor_key(|w| k.write_cbor(w), |w| v.write_cbor(w));
378 }
379 })
380 }
381}
382
383impl<K: ReadCbor + Hash + Eq, V: ReadCbor> ReadCbor for HashMap<K, V> {
384 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
385 where
386 Self: Sized,
387 {
388 let mut map = HashMap::new();
389 for (k, v) in cbor.try_dict()? {
390 map.insert(K::read_cbor(k.as_ref())?, V::read_cbor(v.as_ref())?);
391 }
392 Ok(map)
393 }
394
395 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
396 write!(f, "HashMap<")?;
397 K::fmt(f)?;
398 write!(f, ", ")?;
399 V::fmt(f)?;
400 write!(f, ">")?;
401 Ok(())
402 }
403}
404
405impl<K: WriteCbor> WriteCbor for BTreeSet<K> {
406 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
407 w.encode_array(|mut w| {
408 for k in self {
409 k.write_cbor(&mut w);
410 }
411 })
412 }
413}
414
415impl<K: ReadCbor + Ord> ReadCbor for BTreeSet<K> {
416 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
417 write!(f, "BTreeSet<")?;
418 K::fmt(f)?;
419 write!(f, ">")?;
420 Ok(())
421 }
422
423 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
424 where
425 Self: Sized,
426 {
427 let mut set = Self::new();
428 for k in cbor.try_array()? {
429 set.insert(K::read_cbor(k.as_ref())?);
430 }
431 Ok(set)
432 }
433}
434
435impl<K: WriteCbor> WriteCbor for HashSet<K> {
436 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
437 w.encode_array(|mut w| {
438 for k in self {
439 k.write_cbor(&mut w);
440 }
441 })
442 }
443}
444
445impl<K: ReadCbor + Hash + Eq> ReadCbor for HashSet<K> {
446 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
447 write!(f, "HashSet<")?;
448 K::fmt(f)?;
449 write!(f, ">")?;
450 Ok(())
451 }
452
453 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
454 where
455 Self: Sized,
456 {
457 let mut set = Self::new();
458 for k in cbor.try_array()? {
459 set.insert(K::read_cbor(k.as_ref())?);
460 }
461 Ok(set)
462 }
463}
464
465impl WriteCbor for i128 {
466 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
467 w.encode_number(&Number::Int(*self))
468 }
469}
470
471impl ReadCbor for i128 {
472 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
473 where
474 Self: Sized,
475 {
476 match cbor.try_number()? {
477 Number::Int(x) => Ok(x),
478 x => Err(CodecError::WrongNumber(x.get_type())),
479 }
480 }
481
482 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
483 write!(f, "i128")
484 }
485}
486
487impl WriteCbor for f64 {
488 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
489 w.encode_number(&Number::IEEE754(*self))
490 }
491}
492
493impl ReadCbor for f64 {
494 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
495 where
496 Self: Sized,
497 {
498 match cbor.try_number()? {
499 Number::IEEE754(x) => Ok(x),
500 x => Err(CodecError::WrongNumber(x.get_type())),
501 }
502 }
503
504 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
505 write!(f, "f64")
506 }
507}
508
509impl WriteCbor for Number<'_> {
510 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
511 w.encode_number(self)
512 }
513}
514
515impl ReadCbor for Number<'static> {
516 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
517 write!(f, "Number")
518 }
519
520 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
521 where
522 Self: Sized,
523 {
524 Ok(cbor.try_number()?.make_static())
525 }
526}
527
528impl WriteCbor for Cbor {
529 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
530 w.write_trusting(self.as_slice())
531 }
532}
533
534impl WriteCbor for CborOwned {
535 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
536 w.write_trusting(self.as_slice())
537 }
538}
539
540impl<'a> ReadCborBorrowed<'a> for Cbor {
541 fn read_cbor_borrowed(cbor: &'a Cbor) -> Result<Cow<'a, Self>> {
542 Ok(Cow::Borrowed(cbor))
543 }
544}
545
546impl ReadCbor for CborOwned {
547 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
548 write!(f, "Cbor")
549 }
550
551 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
552 where
553 Self: Sized,
554 {
555 Ok(<Cbor>::read_cbor_borrowed(cbor)?.into_owned())
556 }
557}
558
559macro_rules! tuple {
560 ($($t:ident),+) => {
561 impl<$($t: WriteCbor),*> WriteCbor for ($($t),*) {
562 #[allow(unused_assignments, non_snake_case)]
563 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
564 w.encode_array(|mut w| {
565 let ($($t),*) = self;
566 $(w = $t.write_cbor(w);)*
567 })
568 }
569 }
570 impl<$($t: ReadCbor),*> ReadCbor for ($($t),*) {
571 #[allow(unused_assignments, non_snake_case)]
572 fn read_cbor_impl(cbor: &Cbor) -> Result<Self> {
573 let d = cbor.decode().to_array().ok_or_else(|| CodecError::type_error("tuple", &cbor.tagged_item()))?;
574 let len = $({const $t: usize = 1; $t}+)* 0;
575 if d.len() < len {
576 return Err(CodecError::tuple_size(len, d.len()));
577 }
578 let mut idx = 0;
579 $(
580 let $t = $t::read_cbor(d[idx].as_ref())?;
581 idx += 1;
582 )*
583 Ok(($($t),*))
584 }
585
586 fn fmt(f: &mut impl ::std::fmt::Write) -> std::fmt::Result {
587 write!(f, "(")?;
588 $(
589 $t::fmt(f)?;
590 write!(f, ", ")?;
591 )*
592 write!(f, ")")?;
593 Ok(())
594 }
595 }
596 };
597}
598
599tuple!(T0, T1);
600tuple!(T0, T1, T2);
601tuple!(T0, T1, T2, T3);
602tuple!(T0, T1, T2, T3, T4);
603tuple!(T0, T1, T2, T3, T4, T5);
604tuple!(T0, T1, T2, T3, T4, T5, T6);
605tuple!(T0, T1, T2, T3, T4, T5, T6, T7);
606tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
607tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
608
609impl<T: ?Sized + WriteCbor> WriteCbor for &T {
610 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
611 (*self).write_cbor(w)
612 }
613}
614
615#[macro_export]
616macro_rules! cbor_via {
617 ($t:ty => $u:ty: |$x:pat| -> $xx:expr, |$y:pat| -> $yy:expr) => {
618 impl $crate::codec::WriteCbor for $t {
619 fn write_cbor<W: $crate::Writer>(&self, w: W) -> W::Output {
620 let $x: &$t = self;
621 let u = $xx;
622 $crate::codec::WriteCbor::write_cbor(&u, w)
623 }
624 }
625 impl $crate::codec::ReadCbor for $t {
626 fn read_cbor_impl(cbor: &$crate::Cbor) -> $crate::codec::Result<Self>
627 where
628 Self: Sized,
629 {
630 let $y = <$u>::read_cbor(cbor)?;
631 $yy
632 }
633
634 fn fmt(f: &mut impl ::std::fmt::Write) -> std::fmt::Result {
635 write!(f, stringify!($t))
636 }
637 }
638 };
639 ($t:ty => $u:ty: INTO, $($rest:tt)*) => {
640 cbor_via!($t => $u: |x| -> <$u>::from(x), $($rest)*);
641 };
642 ($t:ty => $u:ty: |$x:ident| -> $xx:expr, FROM) => {
643 cbor_via!($t => $u: |$x| -> $xx, |x| -> Ok(x.into()));
644 };
645 ($t:ty => $u:ty) => {
646 cbor_via!($t => $u: INTO, FROM);
647 };
648}
649
650cbor_via!(u64 => i128: |x| -> i128::from(*x), |x| -> x.try_into().map_err(CodecError::custom));
651cbor_via!(i64 => i128: |x| -> i128::from(*x), |x| -> x.try_into().map_err(CodecError::custom));
652cbor_via!(u32 => i128: |x| -> i128::from(*x), |x| -> x.try_into().map_err(CodecError::custom));
653cbor_via!(i32 => i128: |x| -> i128::from(*x), |x| -> x.try_into().map_err(CodecError::custom));
654cbor_via!(u16 => i128: |x| -> i128::from(*x), |x| -> x.try_into().map_err(CodecError::custom));
655cbor_via!(i16 => i128: |x| -> i128::from(*x), |x| -> x.try_into().map_err(CodecError::custom));
656cbor_via!(f32 => f64: |x| -> f64::from(*x), |x| -> Ok(x as f32));
657
658#[cfg(feature = "libipld14")]
659mod impl_libipld14 {
660 use super::*;
661 use libipld14::{
662 cbor::DagCborCodec,
663 prelude::{Codec, Encode},
664 store::StoreParams,
665 Block, Cid, Ipld,
666 };
667 use smallvec::SmallVec;
668
669 impl WriteCbor for Cid {
670 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
671 let mut bytes = SmallVec::<[u8; 128]>::new();
672 self.write_bytes(&mut bytes).expect("writing to SmallVec");
673 w.write_bytes_chunked([&[0][..], &*bytes], [42])
674 }
675 }
676
677 impl ReadCbor for Cid {
678 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
679 write!(f, "Cid")
680 }
681
682 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
683 where
684 Self: Sized,
685 {
686 let decoded = cbor.tagged_item();
687 if let (Some(42), ItemKind::Bytes(b)) = (decoded.tags().single(), decoded.kind()) {
688 let b = b.as_cow();
689 if b.is_empty() {
690 Err(CodecError::str("Cid cannot be empty"))
691 } else if b[0] != 0 {
692 Err(CodecError::str("Cid must use identity encoding"))
693 } else {
694 Cid::read_bytes(&b[1..]).map_err(CodecError::custom)
695 }
696 } else {
697 Err(CodecError::type_error("Cid", &decoded))
698 }
699 }
700 }
701
702 impl<S: StoreParams> WriteCbor for Block<S> {
703 fn write_cbor<W: Writer>(&self, w: W) -> W::Output {
704 (self.cid(), AsByteString(self.data())).write_cbor(w)
705 }
706 }
707
708 impl<S: StoreParams> ReadCbor for Block<S> {
709 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
710 write!(f, "Block")
711 }
712
713 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
714 where
715 Self: Sized,
716 {
717 let (cid, data) = <(Cid, AsByteString<Vec<u8>>)>::read_cbor(cbor)?;
718 Self::new(cid, data.0).map_err(|err| CodecError::str(err.to_string()))
719 }
720 }
721
722 impl WriteCbor for Ipld {
723 fn write_cbor<W: Writer>(&self, mut w: W) -> W::Output {
724 w.bytes(|b| self.encode(DagCborCodec, b))
725 .expect("WriteCbor for Ipld");
726 w.into_output()
727 }
728 }
729
730 impl ReadCbor for Ipld {
731 fn fmt(f: &mut impl std::fmt::Write) -> std::fmt::Result {
732 write!(f, "Ipld")
733 }
734
735 fn read_cbor_impl(cbor: &Cbor) -> Result<Self>
736 where
737 Self: Sized,
738 {
739 DagCborCodec
740 .decode(cbor.as_slice())
741 .map_err(|err| CodecError::Custom(err.into()))
742 }
743 }
744}
745
746#[cfg(test)]
747mod tests {
748 use super::*;
749 use crate::CborBuilder;
750 use std::convert::TryFrom;
751
752 #[derive(Debug, PartialEq)]
753 struct X(u64);
754 impl From<u64> for X {
755 fn from(x: u64) -> Self {
756 X(x)
757 }
758 }
759 impl From<&X> for u64 {
760 fn from(x: &X) -> Self {
761 x.0
762 }
763 }
764 mod priv1 {
765 use super::X;
766 cbor_via!(X => u64);
767 }
768
769 #[derive(Debug)]
770 struct Z;
771 impl std::fmt::Display for Z {
772 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
773 write!(f, "Z")
774 }
775 }
776 impl Error for Z {}
777 #[derive(Debug, PartialEq)]
778 struct Y(u64);
779 impl TryFrom<u64> for Y {
780 type Error = Z;
781 fn try_from(y: u64) -> std::result::Result<Self, Z> {
782 Ok(Y(y))
783 }
784 }
785 mod priv2 {
786 use crate::codec::CodecError;
787 use std::convert::TryInto;
788
789 cbor_via!(super::Y => u64: |x| -> x.0, |x| -> x.try_into().map_err(CodecError::custom));
790 }
791
792 #[test]
793 fn via() {
794 assert_eq!(X::name(), "X");
795 let bytes = X(5).write_cbor(CborBuilder::default());
796 let x = X::read_cbor(&*bytes).unwrap();
797 assert_eq!(x, X(5));
798
799 assert_eq!(Y::name(), "super::Y");
800 let bytes = Y(5).write_cbor(CborBuilder::default());
801 let y = Y::read_cbor(&*bytes).unwrap();
802 assert_eq!(y, Y(5));
803 }
804
805 #[test]
806 fn tuple() {
807 assert_eq!(<(String, u64)>::name(), "(String, u64, )");
808 let bytes = ("hello".to_owned(), 42u64).write_cbor(CborBuilder::default());
809 let tuple = <(String, u64)>::read_cbor(&*bytes).unwrap();
810 assert_eq!(tuple, ("hello".to_owned(), 42u64));
811 }
812
813 #[test]
814 fn vec() {
815 assert_eq!(<Vec<String>>::name(), "Vec<String>");
816 let x = vec!["hello".to_owned(), "world".to_owned()];
817 let bytes = x.write_cbor(CborBuilder::default());
818 let vec = <Vec<String>>::read_cbor(&*bytes).unwrap();
819 assert_eq!(vec, x);
820 }
821
822 #[test]
823 fn option() {
824 assert_eq!(<Option<String>>::name(), "Option<String>");
825 let x = Some("hello".to_owned());
826 let bytes = x.write_cbor(CborBuilder::default());
827 let opt = <Option<String>>::read_cbor(&*bytes).unwrap();
828 assert_eq!(opt, x);
829
830 let x = None;
831 let bytes = x.write_cbor(CborBuilder::default());
832 let opt = <Option<String>>::read_cbor(&*bytes).unwrap();
833 assert_eq!(opt, x);
834 }
835
836 #[test]
837 fn int() {
838 assert_eq!(u64::name(), "u64");
839 let bytes = 42u64.write_cbor(CborBuilder::default());
840 let x = u64::read_cbor(&*bytes).unwrap();
841 assert_eq!(x, 42);
842 }
843}