libipld_raw_cbor/
decode.rs

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