sp_ipld/dag_cbor/
decode.rs

1use crate::{
2  codec::{
3    Decode,
4    References,
5    SkipOne,
6  },
7  dag_cbor::DagCborCodec,
8  ipld::Ipld,
9};
10
11use alloc::{
12  borrow::ToOwned,
13  boxed::Box,
14  collections::btree_map::BTreeMap,
15  string::{
16    String,
17    ToString,
18  },
19  sync::Arc,
20  vec::Vec,
21};
22use byteorder::{
23  BigEndian,
24  ByteOrder,
25};
26
27use core::{
28  any::type_name,
29  convert::TryFrom,
30};
31
32use bytecursor::{
33  ByteCursor,
34  SeekFrom,
35};
36use sp_cid::Cid;
37
38/// # Errors
39///
40/// Will return `Err` if the `ByteCursor` has less than 1 available bytes to
41/// read
42fn read_u8(r: &mut ByteCursor) -> Result<u8, String> {
43  let mut buf = [0; 1];
44  r.read_exact(&mut buf)?;
45  Ok(buf[0])
46}
47
48/// # Errors
49///
50/// Will return `Err` if the `ByteCursor` has less than 2 available bytes to
51/// read
52fn read_u16(r: &mut ByteCursor) -> Result<u16, String> {
53  let mut buf = [0; 2];
54  r.read_exact(&mut buf)?;
55  Ok(BigEndian::read_u16(&buf))
56}
57
58/// # Errors
59///
60/// Will return `Err` if the `ByteCursor` has less than 4 available bytes to
61/// read
62fn read_u32(r: &mut ByteCursor) -> Result<u32, String> {
63  let mut buf = [0; 4];
64  r.read_exact(&mut buf)?;
65  Ok(BigEndian::read_u32(&buf))
66}
67
68/// # Errors
69///
70/// Will return `Err` if the `ByteCursor` has less than 8 available bytes to
71/// read
72fn read_u64(r: &mut ByteCursor) -> Result<u64, String> {
73  let mut buf = [0; 8];
74  r.read_exact(&mut buf)?;
75  Ok(BigEndian::read_u64(&buf))
76}
77
78/// # Errors
79///
80/// Will return `Err` if the `ByteCursor` has less than 4 available bytes to
81/// read
82fn read_f32(r: &mut ByteCursor) -> Result<f32, String> {
83  let mut buf = [0; 4];
84  r.read_exact(&mut buf)?;
85  Ok(BigEndian::read_f32(&buf))
86}
87
88/// # Errors
89///
90/// Will return `Err` if the `ByteCursor` has less than 8 available bytes to
91/// read
92fn read_f64(r: &mut ByteCursor) -> Result<f64, String> {
93  let mut buf = [0; 8];
94  r.read_exact(&mut buf)?;
95  Ok(BigEndian::read_f64(&buf))
96}
97
98/// # Errors
99///
100/// Will return `Err` if the `ByteCursor` has less than `len` available bytes
101/// to read
102fn read_bytes(r: &mut ByteCursor, len: usize) -> Result<Vec<u8>, String> {
103  let mut buf = vec![0; len];
104  r.read_exact(&mut buf)?;
105  Ok(buf)
106}
107
108/// # Errors
109///
110/// Will return `Err` if the `ByteCursor` has less than `len` available bytes
111/// to read or the bytes read are not valid UTF-8
112fn read_str(r: &mut ByteCursor, len: usize) -> Result<String, String> {
113  let bytes = read_bytes(r, len)?;
114  String::from_utf8(bytes).map_err(|_| "Error converting to UTF-8".to_owned())
115}
116
117/// Will return `Err` if there were any errors decoding `len` objects
118fn read_list<T: Decode<DagCborCodec>>(
119  r: &mut ByteCursor,
120  len: usize,
121) -> Result<Vec<T>, String> {
122  let mut list: Vec<T> = Vec::with_capacity(len);
123  for _ in 0..len {
124    list.push(T::decode(DagCborCodec, r)?);
125  }
126  Ok(list)
127}
128
129/// # Errors
130///
131/// Will return `Err` if there were errors reading the major value, seeking
132/// back, or decoding the component objects
133fn read_list_il<T: Decode<DagCborCodec>>(
134  r: &mut ByteCursor,
135) -> Result<Vec<T>, String> {
136  let mut list: Vec<T> = Vec::new();
137  loop {
138    let major = read_u8(r)?;
139    if major == 0xff {
140      break;
141    }
142    r.seek(&SeekFrom::Current(-1))?;
143    let value = T::decode(DagCborCodec, r)?;
144    list.push(value);
145  }
146  Ok(list)
147}
148
149/// # Errors
150///
151/// Will return `Err` if there were any errors decoding `len` key-value pairs
152/// of objects
153fn read_map<K: Decode<DagCborCodec> + Ord, T: Decode<DagCborCodec>>(
154  r: &mut ByteCursor,
155  len: usize,
156) -> Result<BTreeMap<K, T>, String> {
157  let mut map: BTreeMap<K, T> = BTreeMap::new();
158  for _ in 0..len {
159    let key = K::decode(DagCborCodec, r)?;
160    let value = T::decode(DagCborCodec, r)?;
161    map.insert(key, value);
162  }
163  Ok(map)
164}
165
166/// # Errors
167///
168/// Will return `Err` if there was an error reading the major value, seeking
169/// backward, or decoding the component key-value pairs of objects
170fn read_map_il<K: Decode<DagCborCodec> + Ord, T: Decode<DagCborCodec>>(
171  r: &mut ByteCursor,
172) -> Result<BTreeMap<K, T>, String> {
173  let mut map: BTreeMap<K, T> = BTreeMap::new();
174  loop {
175    let major = read_u8(r)?;
176    if major == 0xff {
177      break;
178    }
179    r.seek(&SeekFrom::Current(-1))?;
180    let key = K::decode(DagCborCodec, r)?;
181    let value = T::decode(DagCborCodec, r)?;
182    map.insert(key, value);
183  }
184  Ok(map)
185}
186
187/// # Errors
188///
189/// Will return `Err` if the `ByteCursor` is not long enough, the cbor tag is
190/// not `0x58`, the len is `0`, `bytes[0]` is not `0`, or if the bytes are not
191/// a valid Cid
192fn read_link(r: &mut ByteCursor) -> Result<Cid, String> {
193  let ty = read_u8(r)?;
194  if ty != 0x58 {
195    return Err(format!("Unknown cbor tag `{}`", ty));
196  }
197  let len = read_u8(r)?;
198  if len == 0 {
199    return Err("Length out of range when decoding Cid.".to_owned());
200  }
201  let bytes = read_bytes(r, len as usize)?;
202  if bytes[0] != 0 {
203    return Err(format!("Invalid Cid prefix: {}", bytes[0]));
204  }
205
206  // skip the first byte per
207  // https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md#links
208  Cid::try_from(&bytes[1..]).map_err(|x| x.to_string())
209}
210
211/// # Errors
212///
213/// Will return `Err` if the major value is unknown or decoding a usize which
214/// is greater than `u64::MAX`
215fn read_len(r: &mut ByteCursor, major: u8) -> Result<usize, String> {
216  Ok(match major {
217    0x00..=0x17 => major as usize,
218    0x18 => read_u8(r)? as usize,
219    0x19 => read_u16(r)? as usize,
220    0x1a => read_u32(r)? as usize,
221    0x1b => {
222      let len = read_u64(r)?;
223      if len > usize::max_value() as u64 {
224        return Err("Length out of range when decoding usize.".to_owned());
225      }
226      len as usize // may truncate
227    }
228    major => {
229      return Err(format!(
230        "Unexpected cbor code `0x{}` when decoding usize.",
231        major
232      ));
233    }
234  })
235}
236impl Decode<DagCborCodec> for bool {
237  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
238    let major = read_u8(r)?;
239    let result = match major {
240      0xf4 => false,
241      0xf5 => true,
242      _ => {
243        return Err(format!(
244          "Unexpected cbor code `0x{}` when decoding bool.",
245          major
246        ));
247      }
248    };
249    Ok(result)
250  }
251}
252impl Decode<DagCborCodec> for u8 {
253  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
254    let major = read_u8(r)?;
255    let result = match major {
256      0x00..=0x17 => major,
257      0x18 => read_u8(r)?,
258      _ => {
259        return Err(format!(
260          "Unexpected cbor code `0x{}` when decoding u8.",
261          major
262        ));
263      }
264    };
265    Ok(result)
266  }
267}
268impl Decode<DagCborCodec> for u16 {
269  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
270    let major = read_u8(r)?;
271    let result = match major {
272      0x00..=0x17 => Self::from(major),
273      0x18 => Self::from(read_u8(r)?),
274      0x19 => read_u16(r)?,
275      _ => {
276        return Err(format!(
277          "Unexpected cbor code `0x{}` when decoding u16.",
278          major
279        ));
280      }
281    };
282    Ok(result)
283  }
284}
285impl Decode<DagCborCodec> for u32 {
286  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
287    let major = read_u8(r)?;
288    let result = match major {
289      0x00..=0x17 => Self::from(major),
290      0x18 => Self::from(read_u8(r)?),
291      0x19 => Self::from(read_u16(r)?),
292      0x1a => read_u32(r)?,
293      _ => {
294        return Err(format!(
295          "Unexpected cbor code `0x{}` when decoding u32.",
296          major
297        ));
298      }
299    };
300    Ok(result)
301  }
302}
303impl Decode<DagCborCodec> for u64 {
304  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
305    let major = read_u8(r)?;
306    let result = match major {
307      0x00..=0x17 => Self::from(major),
308      0x18 => Self::from(read_u8(r)?),
309      0x19 => Self::from(read_u16(r)?),
310      0x1a => Self::from(read_u32(r)?),
311      0x1b => read_u64(r)?,
312      _ => {
313        return Err(format!(
314          "Unexpected cbor code `0x{}` when decoding u64.",
315          major
316        ));
317      }
318    };
319    Ok(result)
320  }
321}
322impl Decode<DagCborCodec> for i8 {
323  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
324    let major = read_u8(r)?;
325    let result = match major {
326      0x20..=0x37 => -1 - (major - 0x20) as Self, // may wrap
327      0x38 => -1 - read_u8(r)? as Self,           // may wrap
328      _ => {
329        return Err(format!(
330          "Unexpected cbor code `0x{}` when decoding i8.",
331          major
332        ));
333      }
334    };
335    Ok(result)
336  }
337}
338impl Decode<DagCborCodec> for i16 {
339  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
340    let major = read_u8(r)?;
341    let result = match major {
342      0x20..=0x37 => -1 - Self::from(major - 0x20),
343      0x38 => -1 - Self::from(read_u8(r)?),
344      0x39 => -1 - read_u16(r)? as Self, // may wrap
345      _ => {
346        return Err(format!(
347          "Unexpected cbor code `0x{}` when decoding i16.",
348          major
349        ));
350      }
351    };
352    Ok(result)
353  }
354}
355impl Decode<DagCborCodec> for i32 {
356  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
357    let major = read_u8(r)?;
358    let result = match major {
359      0x20..=0x37 => -1 - Self::from(major - 0x20),
360      0x38 => -1 - Self::from(read_u8(r)?),
361      0x39 => -1 - Self::from(read_u16(r)?),
362      0x3a => -1 - read_u32(r)? as Self, // may wrap
363      _ => {
364        return Err(format!(
365          "Unexpected cbor code `0x{}` when decoding i32.",
366          major
367        ));
368      }
369    };
370    Ok(result)
371  }
372}
373impl Decode<DagCborCodec> for i64 {
374  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
375    let major = read_u8(r)?;
376    let result = match major {
377      0x20..=0x37 => -1 - Self::from(major - 0x20),
378      0x38 => -1 - Self::from(read_u8(r)?),
379      0x39 => -1 - Self::from(read_u16(r)?),
380      0x3a => -1 - Self::from(read_u32(r)?),
381      0x3b => -1 - read_u64(r)? as Self, // may wrap
382      _ => {
383        return Err(format!(
384          "Unexpected cbor code `0x{}` when decoding i64.",
385          major
386        ));
387      }
388    };
389    Ok(result)
390  }
391}
392impl Decode<DagCborCodec> for f32 {
393  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
394    let major = read_u8(r)?;
395    let result = match major {
396      0xfa => read_f32(r)?,
397      _ => {
398        return Err(format!(
399          "Unexpected cbor code `0x{}` when decoding f32.",
400          major
401        ));
402      }
403    };
404    Ok(result)
405  }
406}
407impl Decode<DagCborCodec> for f64 {
408  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
409    let major = read_u8(r)?;
410    let result = match major {
411      0xfa => Self::from(read_f32(r)?),
412      0xfb => read_f64(r)?,
413      _ => {
414        return Err(format!(
415          "Unexpected cbor code `0x{}` when decoding f64.",
416          major
417        ));
418      }
419    };
420    Ok(result)
421  }
422}
423
424impl Decode<DagCborCodec> for String {
425  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
426    let major = read_u8(r)?;
427    let result = match major {
428      0x60..=0x7b => {
429        let len = read_len(r, major - 0x60)?;
430        read_str(r, len)?
431      }
432      _ => {
433        return Err(format!(
434          "Unexpected cbor code `0x{}` when decoding String.",
435          major
436        ));
437      }
438    };
439    Ok(result)
440  }
441}
442impl Decode<DagCborCodec> for Cid {
443  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
444    let major = read_u8(r)?;
445    if major == 0xd8 {
446      if let Ok(tag) = read_u8(r) {
447        if tag == 42 {
448          return read_link(r);
449        }
450      }
451    }
452    Err(format!("Unexpected cbor code `0x{}` when decoding Cid.", major))
453  }
454}
455impl Decode<DagCborCodec> for Box<[u8]> {
456  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
457    let major = read_u8(r)?;
458    let result = match major {
459      0x40..=0x5b => {
460        let len = read_len(r, major - 0x40)?;
461        read_bytes(r, len)?.into_boxed_slice()
462      }
463      _ => {
464        return Err(format!(
465          "Unexpected cbor code `0x{}` when decoding Box<[u8]>.",
466          major
467        ));
468      }
469    };
470    Ok(result)
471  }
472}
473impl<T: Decode<DagCborCodec>> Decode<DagCborCodec> for Option<T> {
474  fn decode(c: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
475    let major = read_u8(r)?;
476    let result = match major {
477      0xf6 | 0xf7 => None,
478      _ => {
479        r.seek(&SeekFrom::Current(-1))?;
480        Some(T::decode(c, r)?)
481      }
482    };
483    Ok(result)
484  }
485}
486impl<T: Decode<DagCborCodec>> Decode<DagCborCodec> for Vec<T> {
487  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
488    let major = read_u8(r)?;
489    let result = match major {
490      0x80..=0x9b => {
491        let len = read_len(r, major - 0x80)?;
492        read_list(r, len)?
493      }
494      0x9f => read_list_il(r)?,
495      _ => {
496        return Err(format!(
497          "Unexpected cbor code `0x{}` when decoding Vec<{}>.",
498          major,
499          type_name::<T>()
500        ));
501      }
502    };
503    Ok(result)
504  }
505}
506impl<K: Decode<DagCborCodec> + Ord, T: Decode<DagCborCodec>>
507  Decode<DagCborCodec> for BTreeMap<K, T>
508{
509  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
510    let major = read_u8(r)?;
511    let result = match major {
512      0xa0..=0xbb => {
513        let len = read_len(r, major - 0xa0)?;
514        read_map(r, len)?
515      }
516      0xbf => read_map_il(r)?,
517      _ => {
518        return Err(format!(
519          "Unexpected cbor code `0x{}` when decoding BTreeMap<{}, {}>.",
520          major,
521          type_name::<K>(),
522          type_name::<T>()
523        ));
524      }
525    };
526    Ok(result)
527  }
528}
529impl Decode<DagCborCodec> for Ipld {
530  fn decode(_: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
531    let major = read_u8(r)?;
532    let ipld = match major {
533      // Major type 0: an unsigned integer
534      0x00..=0x17 => Self::Integer(i128::from(major)),
535      0x18 => Self::Integer(i128::from(read_u8(r)?)),
536      0x19 => Self::Integer(i128::from(read_u16(r)?)),
537      0x1a => Self::Integer(i128::from(read_u32(r)?)),
538      0x1b => Self::Integer(i128::from(read_u64(r)?)),
539
540      // Major type 1: a negative integer
541      0x20..=0x37 => Self::Integer(-1 - i128::from(major - 0x20)),
542      0x38 => Self::Integer(-1 - i128::from(read_u8(r)?)),
543      0x39 => Self::Integer(-1 - i128::from(read_u16(r)?)),
544      0x3a => Self::Integer(-1 - i128::from(read_u32(r)?)),
545      0x3b => Self::Integer(-1 - i128::from(read_u64(r)?)),
546
547      // Major type 2: a byte string
548      0x40..=0x5b => {
549        let len = read_len(r, major - 0x40)?;
550        let bytes = read_bytes(r, len as usize)?;
551        Self::Bytes(bytes)
552      }
553
554      // Major type 3: a text string
555      0x60..=0x7b => {
556        let len = read_len(r, major - 0x60)?;
557        let string = read_str(r, len as usize)?;
558        Self::String(string)
559      }
560
561      // Major type 4: an array of data items
562      0x80..=0x9b => {
563        let len = read_len(r, major - 0x80)?;
564        let list = read_list(r, len as usize)?;
565        Self::List(list)
566      }
567
568      // Major type 4: an array of data items (indefinite length)
569      0x9f => {
570        let list = read_list_il(r)?;
571        Self::List(list)
572      }
573
574      // Major type 5: a map of pairs of data items
575      0xa0..=0xbb => {
576        let len = read_len(r, major - 0xa0)?;
577        Self::StringMap(read_map(r, len as usize)?)
578      }
579
580      // Major type 5: a map of pairs of data items (indefinite length)
581      0xbf => {
582        let pos = r.seek(&SeekFrom::Current(0))?;
583        r.seek(&SeekFrom::Start(pos))?;
584        Self::StringMap(read_map_il(r)?)
585      }
586
587      // Major type 6: optional semantic tagging of other major types
588      0xd8 => {
589        let tag = read_u8(r)?;
590        if tag == 42 {
591          Self::Link(read_link(r)?)
592        }
593        else {
594          return Err(format!("Unknown cbor tag `{}`", tag));
595        }
596      }
597
598      // Major type 7: floating-point numbers and other simple data types that
599      // need no content
600      0xf4 => Self::Bool(false),
601      0xf5 => Self::Bool(true),
602      0xf6 | 0xf7 => Self::Null,
603      0xfa => Self::Float(f64::from(read_f32(r)?)),
604      0xfb => Self::Float(read_f64(r)?),
605      _ => {
606        return Err(format!(
607          "Unexpected cbor code `0x{}` when decoding Ipld.",
608          major,
609        ));
610      }
611    };
612    Ok(ipld)
613  }
614}
615
616impl References<DagCborCodec> for Ipld {
617  fn references<E: Extend<Cid>>(
618    c: DagCborCodec,
619    r: &mut ByteCursor,
620    set: &mut E,
621  ) -> Result<(), String> {
622    let major = read_u8(r)?;
623    match major {
624      0x00..=0x17 | 0x20..=0x37 | 0xf4..=0xf7 => {}
625
626      0x18 | 0x38 | 0xf8 => {
627        r.seek(&SeekFrom::Current(1))?;
628      }
629      0x19 | 0x39 | 0xf9 => {
630        r.seek(&SeekFrom::Current(2))?;
631      }
632      0x1a | 0x3a | 0xfa => {
633        r.seek(&SeekFrom::Current(4))?;
634      }
635      0x1b | 0x3b | 0xfb => {
636        r.seek(&SeekFrom::Current(8))?;
637      }
638
639      // Major type 2: a byte string
640      0x40..=0x5b => {
641        let len = read_len(r, major - 0x40)?;
642        r.seek(&SeekFrom::Current(len as _))?;
643      }
644
645      // Major type 3: a text string
646      0x60..=0x7b => {
647        let len = read_len(r, major - 0x60)?;
648        r.seek(&SeekFrom::Current(len as _))?;
649      }
650
651      // Major type 4: an array of data items
652      0x80..=0x9b => {
653        let len = read_len(r, major - 0x80)?;
654        for _ in 0..len {
655          <Self as References<DagCborCodec>>::references(c, r, set)?;
656        }
657      }
658
659      // Major type 4: an array of data items (indefinite length)
660      0x9f => loop {
661        let major = read_u8(r)?;
662        if major == 0xff {
663          break;
664        }
665        r.seek(&SeekFrom::Current(-1))?;
666        <Self as References<DagCborCodec>>::references(c, r, set)?;
667      },
668
669      // Major type 5: a map of pairs of data items
670      0xa0..=0xbb => {
671        let len = read_len(r, major - 0xa0)?;
672        for _ in 0..len {
673          <Self as References<DagCborCodec>>::references(c, r, set)?;
674          <Self as References<DagCborCodec>>::references(c, r, set)?;
675        }
676      }
677
678      // Major type 5: a map of pairs of data items (indefinite length)
679      0xbf => loop {
680        let major = read_u8(r)?;
681        if major == 0xff {
682          break;
683        }
684        r.seek(&SeekFrom::Current(-1))?;
685        <Self as References<DagCborCodec>>::references(c, r, set)?;
686        <Self as References<DagCborCodec>>::references(c, r, set)?;
687      },
688
689      // Major type 6: optional semantic tagging of other major types
690      0xd8 => {
691        let tag = read_u8(r)?;
692        if tag == 42 {
693          set.extend(core::iter::once(read_link(r)?));
694        }
695        else {
696          <Self as References<DagCborCodec>>::references(c, r, set)?;
697        }
698      }
699
700      major => {
701        return Err(format!(
702          "Unexpected cbor code `0x{}` when decoding Ipld.",
703          major
704        ));
705      }
706    };
707    Ok(())
708  }
709}
710impl<T: Decode<DagCborCodec>> Decode<DagCborCodec> for Arc<T> {
711  fn decode(c: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
712    Ok(Self::new(T::decode(c, r)?))
713  }
714}
715impl Decode<DagCborCodec> for () {
716  fn decode(_c: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
717    let major = read_u8(r)?;
718    match major {
719      0x80 => {}
720      _ => {
721        return Err(format!(
722          "Unexpected cbor code `0x{}` when decoding ().",
723          major
724        ));
725      }
726    };
727    Ok(())
728  }
729}
730impl<A: Decode<DagCborCodec>> Decode<DagCborCodec> for (A,) {
731  fn decode(c: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
732    let major = read_u8(r)?;
733    let result = match major {
734      0x81 => (A::decode(c, r)?,),
735      _ => {
736        return Err(format!(
737          "Unexpected cbor code `0x{}` when decoding {}.",
738          major,
739          type_name::<Self>()
740        ));
741      }
742    };
743    Ok(result)
744  }
745}
746impl<A: Decode<DagCborCodec>, B: Decode<DagCborCodec>> Decode<DagCborCodec>
747  for (A, B)
748{
749  fn decode(c: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
750    let major = read_u8(r)?;
751    let result = match major {
752      0x82 => (A::decode(c, r)?, B::decode(c, r)?),
753      _ => {
754        return Err(format!(
755          "Unexpected cbor code `0x{}` when decoding {}.",
756          major,
757          type_name::<Self>()
758        ));
759      }
760    };
761    Ok(result)
762  }
763}
764impl<A: Decode<DagCborCodec>, B: Decode<DagCborCodec>, C: Decode<DagCborCodec>>
765  Decode<DagCborCodec> for (A, B, C)
766{
767  fn decode(c: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
768    let major = read_u8(r)?;
769    let result = match major {
770      0x83 => (A::decode(c, r)?, B::decode(c, r)?, C::decode(c, r)?),
771      _ => {
772        return Err(format!(
773          "Unexpected cbor code `0x{}` when decoding {}.",
774          major,
775          type_name::<Self>()
776        ));
777      }
778    };
779    Ok(result)
780  }
781}
782impl<
783  A: Decode<DagCborCodec>,
784  B: Decode<DagCborCodec>,
785  C: Decode<DagCborCodec>,
786  D: Decode<DagCborCodec>,
787> Decode<DagCborCodec> for (A, B, C, D)
788{
789  fn decode(c: DagCborCodec, r: &mut ByteCursor) -> Result<Self, String> {
790    let major = read_u8(r)?;
791    let result = match major {
792      0x84 => {
793        (A::decode(c, r)?, B::decode(c, r)?, C::decode(c, r)?, D::decode(c, r)?)
794      }
795      _ => {
796        return Err(format!(
797          "Unexpected cbor code `0x{}` when decoding {}.",
798          major,
799          type_name::<Self>()
800        ));
801      }
802    };
803    Ok(result)
804  }
805}
806impl SkipOne for DagCborCodec {
807  fn skip(&self, r: &mut ByteCursor) -> Result<(), String> {
808    let major = read_u8(r)?;
809    match major {
810      // Major type 0: an unsigned integer
811      0x00..=0x17 | 0x20..=0x37 | 0xf4..=0xf7 => {}
812      0x18 | 0x38 | 0xf8 => {
813        r.seek(&SeekFrom::Current(1))?;
814      }
815      0x19 | 0x39 | 0xf9 => {
816        r.seek(&SeekFrom::Current(2))?;
817      }
818      0x1a | 0x3a | 0xfa => {
819        r.seek(&SeekFrom::Current(4))?;
820      }
821      0x1b | 0x3b | 0xfb => {
822        r.seek(&SeekFrom::Current(8))?;
823      }
824
825      // Major type 2: a byte string
826      0x40..=0x5b => {
827        let len = read_len(r, major - 0x40)?;
828        r.seek(&SeekFrom::Current(len as _))?;
829      }
830
831      // Major type 3: a text string
832      0x60..=0x7b => {
833        let len = read_len(r, major - 0x60)?;
834        r.seek(&SeekFrom::Current(len as _))?;
835      }
836
837      // Major type 4: an array of data items
838      0x80..=0x9b => {
839        let len = read_len(r, major - 0x80)?;
840        for _ in 0..len {
841          self.skip(r)?;
842        }
843      }
844
845      // Major type 4: an array of data items (indefinite length)
846      0x9f => loop {
847        let major = read_u8(r)?;
848        if major == 0xff {
849          break;
850        }
851        r.seek(&SeekFrom::Current(-1))?;
852        self.skip(r)?;
853      },
854
855      // Major type 5: a map of pairs of data items
856      0xa0..=0xbb => {
857        let len = read_len(r, major - 0xa0)?;
858        for _ in 0..len {
859          self.skip(r)?;
860          self.skip(r)?;
861        }
862      }
863
864      // Major type 5: a map of pairs of data items (indefinite length)
865      0xbf => loop {
866        let major = read_u8(r)?;
867        if major == 0xff {
868          break;
869        }
870        r.seek(&SeekFrom::Current(-1))?;
871        self.skip(r)?;
872        self.skip(r)?;
873      },
874
875      // Major type 6: optional semantic tagging of other major types
876      0xd8 => {
877        let _tag = read_u8(r)?;
878        self.skip(r)?;
879      }
880
881      major => {
882        return Err(format!(
883          "Unexpected cbor code `0x{}` when decoding Ipld.",
884          major
885        ));
886      }
887    };
888    Ok(())
889  }
890}