wasm_msgpack/decode/
mod.rs

1#[cfg(feature = "serde")]
2mod serde;
3
4use crate::marker::Marker;
5
6use byteorder::{BigEndian, ByteOrder};
7use num_traits::cast::FromPrimitive;
8use zerocopy::ByteSlice;
9
10/// Error type indicating why deserialization failed
11#[derive(Debug)]
12pub enum Error {
13    /// End of buffer was reached, before object was deserialized.
14    EndOfBuffer(Marker),
15    /// Value was out of bounds. This can happen if for example a `u32` value is deserialized into `u16`.
16    ///
17    /// # Examples
18    ///
19    /// `[0xcd, 0x12, 0x34]` deserializes to `0x1234`. If you try to serialize into `u8`, this error will occur.
20    OutOfBounds,
21    /// Happens if the data type does not match the expected type.
22    InvalidType,
23    CustomError,
24    #[cfg(all(not(feature = "std"), feature = "custom-error-messages"))]
25    CustomErrorWithMessage(heapless::String<64>),
26    #[cfg(all(feature = "std", feature = "custom-error-messages"))]
27    CustomErrorWithMessage(String),
28    NotAscii,
29    InvalidBoolean,
30    InvalidBinType,
31    InvalidStringType,
32    InvalidArrayType,
33    InvalidMapType,
34    InvalidNewTypeLength,
35    InvalidUtf8(core::str::Utf8Error),
36}
37
38#[cfg(feature = "serde")]
39// #[inline(never)]
40pub fn from_slice<'a, T: ::serde::de::Deserialize<'a>>(buf: &'a [u8]) -> Result<T, Error> {
41    let mut de = serde::Deserializer::new(buf);
42    let value = ::serde::de::Deserialize::deserialize(&mut de)?;
43
44    Ok(value)
45}
46
47pub trait DeserializeFromSlice {
48    fn from_slice(&mut self, buf: &[u8]) -> Result<usize, Error>;
49}
50
51impl DeserializeFromSlice for Option<u8> {
52    fn from_slice(&mut self, buf: &[u8]) -> Result<usize, Error> {
53        let (v, n) = read_u8(buf)?;
54        *self = Some(v);
55        Ok(n)
56    }
57}
58impl DeserializeFromSlice for Option<u16> {
59    fn from_slice(&mut self, buf: &[u8]) -> Result<usize, Error> {
60        let (v, n) = read_u16(buf)?;
61        *self = Some(v);
62        Ok(n)
63    }
64}
65impl DeserializeFromSlice for Option<u32> {
66    fn from_slice(&mut self, buf: &[u8]) -> Result<usize, Error> {
67        let (v, n) = read_u32(buf)?;
68        *self = Some(v);
69        Ok(n)
70    }
71}
72impl DeserializeFromSlice for Option<u64> {
73    fn from_slice(&mut self, buf: &[u8]) -> Result<usize, Error> {
74        let (v, n) = read_u64(buf)?;
75        *self = Some(v);
76        Ok(n)
77    }
78}
79impl DeserializeFromSlice for Option<i8> {
80    fn from_slice(&mut self, buf: &[u8]) -> Result<usize, Error> {
81        let (v, n) = read_i8(buf)?;
82        *self = Some(v);
83        Ok(n)
84    }
85}
86impl DeserializeFromSlice for Option<i16> {
87    fn from_slice(&mut self, buf: &[u8]) -> Result<usize, Error> {
88        let (v, n) = read_i16(buf)?;
89        *self = Some(v);
90        Ok(n)
91    }
92}
93impl DeserializeFromSlice for Option<i32> {
94    fn from_slice(&mut self, buf: &[u8]) -> Result<usize, Error> {
95        let (v, n) = read_i32(buf)?;
96        *self = Some(v);
97        Ok(n)
98    }
99}
100impl DeserializeFromSlice for Option<i64> {
101    fn from_slice(&mut self, buf: &[u8]) -> Result<usize, Error> {
102        let (v, n) = read_i64(buf)?;
103        *self = Some(v);
104        Ok(n)
105    }
106}
107
108pub fn read_raw_u8(buf: &[u8]) -> Result<(u8, &[u8]), Error> {
109    buf.split_first().map(|(&x, rest)| (x, rest)).ok_or(Error::EndOfBuffer(Marker::U8))
110}
111pub fn read_raw_u16<B: ByteSlice>(buf: B) -> Result<(u16, B), Error> {
112    // pub fn read_raw_u16(buf: &[u8]) -> Result<(u16, &[u8]), Error> {
113    if buf.len() < 2 {
114        return Err(Error::EndOfBuffer(Marker::U16));
115    }
116    let (v, rest) = buf.split_at(2);
117    Ok((BigEndian::read_u16(&*v), rest))
118}
119pub fn read_raw_u32(buf: &[u8]) -> Result<(u32, &[u8]), Error> {
120    if buf.len() < 4 {
121        return Err(Error::EndOfBuffer(Marker::U32));
122    }
123    let (v, rest) = buf.split_at(4);
124    Ok((BigEndian::read_u32(v), rest))
125}
126#[cfg(feature = "u64")]
127pub fn read_raw_u64(buf: &[u8]) -> Result<(u64, &[u8]), Error> {
128    if buf.len() < 8 {
129        return Err(Error::EndOfBuffer(Marker::U64));
130    }
131    let (v, rest) = buf.split_at(8);
132    Ok((BigEndian::read_u64(v), rest))
133}
134#[allow(dead_code)]
135fn read_raw_ux(buf: &[u8], num_bytes: u8) -> Result<(usize, &[u8]), Error> {
136    Ok(match num_bytes {
137        1 => {
138            let (x, rest) = read_raw_u8(buf)?;
139            (x as usize, rest)
140        }
141        2 => {
142            let (x, rest) = read_raw_u16(buf)?;
143            (x as usize, rest)
144        }
145        4 => {
146            let (x, rest) = read_raw_u32(buf)?;
147            (x as usize, rest)
148        }
149        _ => unreachable!(),
150    })
151}
152
153pub fn read_int<B: ByteSlice, T: FromPrimitive>(buf: B) -> Result<(T, usize), Error> {
154    match read_u64(buf) {
155        Ok((v, len)) => T::from_u64(v).map_or(Err(Error::OutOfBounds), |v| Ok((v, len))),
156        Err(kind) => Err(kind),
157    }
158}
159#[cfg(feature = "i64")]
160pub fn read_sint<B: ByteSlice, T: FromPrimitive>(buf: B) -> Result<(T, usize), Error> {
161    match read_i64(buf) {
162        Ok((v, len)) => T::from_i64(v).map_or(Err(Error::OutOfBounds), |v| Ok((v, len))),
163        Err(kind) => Err(kind),
164    }
165}
166#[cfg(not(feature = "i64"))]
167pub fn read_sint<B: ByteSlice, T: FromPrimitive>(buf: B) -> Result<(T, usize), Error> {
168    match read_i32(buf) {
169        Ok((v, len)) => {
170            if let Some(v) = T::from_i32(v) {
171                Ok((v, len))
172            } else {
173                Err(Error::OutOfBounds)
174            }
175        }
176        Err(kind) => Err(kind),
177    }
178}
179
180#[inline(always)]
181pub fn read_u8<B: ByteSlice>(buf: B) -> Result<(u8, usize), Error> {
182    read_int(buf)
183}
184#[inline(always)]
185pub fn read_u16<B: ByteSlice>(buf: B) -> Result<(u16, usize), Error> {
186    read_int(buf)
187}
188#[inline(always)]
189pub fn read_u32<B: ByteSlice>(buf: B) -> Result<(u32, usize), Error> {
190    read_int(buf)
191}
192
193#[inline(always)]
194pub fn read_i8<B: ByteSlice>(buf: B) -> Result<(i8, usize), Error> {
195    read_sint(buf)
196}
197#[inline(always)]
198pub fn read_i16<B: ByteSlice>(buf: B) -> Result<(i16, usize), Error> {
199    read_sint(buf)
200}
201#[inline(always)]
202pub fn read_i32<B: ByteSlice>(buf: B) -> Result<(i32, usize), Error> {
203    read_sint(buf)
204}
205
206pub fn read_bool<B: ByteSlice>(buf: B) -> Result<(bool, usize), Error> {
207    if buf.len() == 0 {
208        return Err(Error::EndOfBuffer(Marker::True));
209    }
210
211    match Marker::from(buf[0]) {
212        Marker::True => Ok((true, 1)),
213        Marker::False => Ok((false, 1)),
214        _ => Err(Error::InvalidBoolean),
215    }
216}
217
218pub fn read_u64<B: ByteSlice>(buf: B) -> Result<(u64, usize), Error> {
219    if buf.len() == 0 {
220        return Err(Error::EndOfBuffer(Marker::U64));
221    }
222
223    let marker = Marker::from(buf[0]);
224    match marker {
225        // Nur u64 muss hier gesondert behandelt werden, weil es der einzige Typ ist, der potentiell nicht in i64 passt
226        Marker::U64 => {
227            if buf.len() >= 9 {
228                Ok((BigEndian::read_u64(&buf[1..9]), 9))
229            } else {
230                Err(Error::EndOfBuffer(Marker::U64))
231            }
232        }
233        _ => match read_i64(buf) {
234            Ok((i, l)) => u64::from_i64(i).map_or(Err(Error::OutOfBounds), |u| Ok((u, l))),
235            Err(kind) => Err(kind),
236        },
237    }
238}
239
240pub fn read_i64<B: ByteSlice>(buf: B) -> Result<(i64, usize), Error> {
241    if buf.len() == 0 {
242        return Err(Error::EndOfBuffer(Marker::I64));
243    }
244
245    let marker = Marker::from(buf[0]);
246    match marker {
247        Marker::FixPos(val) => Ok((i64::from(val), 1)),
248        Marker::FixNeg(val) => Ok((i64::from(val), 1)),
249
250        Marker::U8 => {
251            if buf.len() >= 2 {
252                Ok((i64::from(buf[1]), 2))
253            } else {
254                Err(Error::EndOfBuffer(Marker::I64))
255            }
256        }
257        Marker::U16 => {
258            if buf.len() >= 3 {
259                Ok((i64::from(BigEndian::read_u16(&buf[1..3])), 3))
260            } else {
261                Err(Error::EndOfBuffer(Marker::I64))
262            }
263        }
264        Marker::U32 => {
265            if buf.len() >= 5 {
266                Ok((i64::from(BigEndian::read_u32(&buf[1..5])), 5))
267            } else {
268                Err(Error::EndOfBuffer(Marker::I64))
269            }
270        }
271        Marker::U64 => {
272            if buf.len() >= 9 {
273                let u = BigEndian::read_u64(&buf[1..9]);
274                i64::from_u64(u).map_or(Err(Error::OutOfBounds), |i| Ok((i, 9)))
275            } else {
276                Err(Error::EndOfBuffer(Marker::I64))
277            }
278        }
279        #[allow(clippy::cast_possible_wrap)]
280        Marker::I8 => {
281            if buf.len() >= 2 {
282                Ok((i64::from(buf[1] as i8), 2))
283            } else {
284                Err(Error::EndOfBuffer(Marker::I64))
285            }
286        }
287        Marker::I16 => {
288            if buf.len() >= 3 {
289                Ok((i64::from(BigEndian::read_i16(&buf[1..3])), 3))
290            } else {
291                Err(Error::EndOfBuffer(Marker::I64))
292            }
293        }
294        Marker::I32 => {
295            if buf.len() >= 5 {
296                Ok((i64::from(BigEndian::read_i32(&buf[1..5])), 5))
297            } else {
298                Err(Error::EndOfBuffer(Marker::I64))
299            }
300        }
301        Marker::I64 => {
302            if buf.len() >= 9 {
303                Ok((BigEndian::read_i64(&buf[1..9]), 9))
304            } else {
305                Err(Error::EndOfBuffer(Marker::I64))
306            }
307        }
308        _ => Err(Error::EndOfBuffer(Marker::I64)),
309    }
310}
311
312pub fn read_f32<B: ByteSlice>(buf: B) -> Result<(f32, usize), Error> {
313    if buf.len() == 0 {
314        return Err(Error::EndOfBuffer(Marker::F32));
315    }
316
317    let marker = Marker::from(buf[0]);
318    match marker {
319        Marker::F32 => {
320            if buf.len() >= 5 {
321                Ok((BigEndian::read_f32(&buf[1..5]), 5))
322            } else {
323                Err(Error::EndOfBuffer(Marker::F32))
324            }
325        }
326        _ => Err(Error::EndOfBuffer(Marker::F32)),
327    }
328}
329pub fn read_f64<B: ByteSlice>(buf: B) -> Result<(f64, usize), Error> {
330    if buf.len() == 0 {
331        return Err(Error::EndOfBuffer(Marker::F64));
332    }
333
334    let marker = Marker::from(buf[0]);
335
336    match marker {
337        Marker::F32 => {
338            if buf.len() >= 5 {
339                let v = BigEndian::read_f32(&buf[1..5]);
340                Ok((f64::from(v), 5))
341            } else {
342                Err(Error::EndOfBuffer(Marker::F32))
343            }
344        }
345        Marker::F64 => {
346            if buf.len() >= 9 {
347                Ok((BigEndian::read_f64(&buf[1..9]), 9))
348            } else {
349                Err(Error::EndOfBuffer(Marker::F64))
350            }
351        }
352        Marker::FixPos(v) => Ok((f64::from(v), 1)),
353        _ => Err(Error::EndOfBuffer(Marker::F64)),
354    }
355}
356
357pub fn read_bin<B: ByteSlice>(buf: B) -> Result<(B, usize), Error> {
358    if buf.len() == 0 {
359        return Err(Error::EndOfBuffer(Marker::Bin16));
360    }
361
362    let marker = Marker::from(buf[0]);
363    match marker {
364        Marker::FixStr(len) => {
365            let header_len = 1;
366            let len = len as usize;
367            if buf.len() >= header_len + len {
368                let (_head, rest) = buf.split_at(header_len);
369                let (bin, _rest) = rest.split_at(len);
370                Ok((bin, header_len + len))
371            } else {
372                Err(Error::EndOfBuffer(Marker::FixStr(len as u8)))
373            }
374        }
375        Marker::Bin8 | Marker::Str8 => {
376            let header_len = 2;
377            if let Some(&len) = buf.get(1) {
378                let len = len as usize;
379                if buf.len() >= header_len + len {
380                    let (_head, rest) = buf.split_at(header_len);
381                    let (bin, _rest) = rest.split_at(len);
382                    Ok((bin, header_len + len))
383                } else {
384                    Err(Error::EndOfBuffer(Marker::Bin8))
385                }
386            } else {
387                Err(Error::EndOfBuffer(Marker::Bin8))
388            }
389        }
390        Marker::Bin16 | Marker::Str16 => {
391            let header_len = 3;
392            if buf.len() < header_len {
393                return Err(Error::EndOfBuffer(Marker::Bin16));
394            }
395            let (_, buf) = buf.split_at(1);
396            let (len, buf) = read_raw_u16(buf)?; //BigEndian::read_u16(&buf[1..header_len]) as usize;
397            let len = len as usize;
398            if buf.len() >= len {
399                let (bin, _rest) = buf.split_at(len);
400                Ok((bin, header_len + len))
401            } else {
402                Err(Error::EndOfBuffer(Marker::Bin16))
403            }
404        }
405        #[cfg(feature = "bin32")]
406        Marker::Bin32 | Marker::Str32 => {
407            let header_len = 5;
408            if buf.len() < header_len {
409                return Err(Error::EndOfBuffer(Marker::Bin32));
410            }
411            let len = BigEndian::read_u32(&buf[1..header_len]) as usize;
412            if buf.len() >= header_len + len {
413                let (_head, rest) = buf.split_at(header_len);
414                let (bin, _rest) = rest.split_at(len);
415                Ok((bin, header_len + len))
416            } else {
417                Err(Error::EndOfBuffer(Marker::Bin32))
418            }
419        }
420        _ => Err(Error::InvalidBinType),
421    }
422}
423
424pub fn read_str(buf: &[u8]) -> Result<(&str, usize), Error> {
425    if buf.is_empty() {
426        return Err(Error::EndOfBuffer(Marker::Str32));
427    }
428
429    let marker = Marker::from(buf[0]);
430    let (header_len, len) = match marker {
431        Marker::FixStr(len) => {
432            let header_len = 1;
433            let len = len as usize;
434            if buf.len() >= header_len + len {
435                (header_len, len)
436            } else {
437                return Err(Error::EndOfBuffer(Marker::FixStr(len as u8)));
438            }
439        }
440        Marker::Str8 => {
441            let header_len = 2;
442            if let Some(&len) = buf.get(1) {
443                let len = len as usize;
444                if buf.len() >= header_len + len {
445                    (header_len, len)
446                } else {
447                    return Err(Error::EndOfBuffer(Marker::Str8));
448                }
449            } else {
450                return Err(Error::EndOfBuffer(Marker::Str8));
451            }
452        }
453        Marker::Str16 => {
454            let header_len = 3;
455            if buf.len() < header_len {
456                return Err(Error::EndOfBuffer(Marker::Str16));
457            }
458            let len = BigEndian::read_u16(&buf[1..header_len]) as usize;
459            if buf.len() >= header_len + len {
460                (header_len, len)
461            } else {
462                return Err(Error::EndOfBuffer(Marker::Str16));
463            }
464        }
465        #[cfg(feature = "str32")]
466        Marker::Str32 => {
467            let header_len = 5;
468            if buf.len() < header_len {
469                return Err(Error::EndOfBuffer(Marker::Str32));
470            }
471            let len = BigEndian::read_u32(&buf[1..header_len]) as usize;
472            if buf.len() >= header_len + len {
473                (header_len, len)
474            } else {
475                return Err(Error::EndOfBuffer(Marker::Str32));
476            }
477        }
478        _ => {
479            return Err(Error::InvalidStringType);
480        }
481    };
482    let buf = &buf[header_len..header_len + len];
483    let s = core::str::from_utf8(buf).map_err(Error::InvalidUtf8)?;
484
485    Ok((s, header_len + len))
486}
487
488pub fn read_array_len<B: ByteSlice>(buf: B) -> Result<(usize, usize), Error> {
489    if buf.len() == 0 {
490        return Err(Error::EndOfBuffer(Marker::Array32));
491    }
492
493    // let (&marker, buf) = buf.split_first().ok_or(Error::EndOfBuffer)?;
494    let marker = Marker::from(buf[0]);
495    let (header_len, len) = match marker {
496        Marker::FixArray(len) => {
497            let header_len = 1;
498            let len = len as usize;
499            if buf.len() >= header_len + len {
500                (header_len, len)
501            } else {
502                return Err(Error::EndOfBuffer(Marker::FixArray(len as u8)));
503            }
504        }
505        #[cfg(feature = "array16")]
506        Marker::Array16 => {
507            let header_len = 3;
508            if buf.len() < header_len {
509                return Err(Error::EndOfBuffer(Marker::Array16));
510            }
511            let len = BigEndian::read_u16(&buf[1..header_len]) as usize;
512            if buf.len() >= header_len + len {
513                (header_len, len)
514            } else {
515                return Err(Error::EndOfBuffer(Marker::Array16));
516            }
517        }
518        #[cfg(feature = "array32")]
519        Marker::Array32 => {
520            let header_len = 5;
521            if buf.len() < header_len {
522                return Err(Error::EndOfBuffer(Marker::Array32));
523            }
524            let len = BigEndian::read_u32(&buf[1..header_len]) as usize;
525            if buf.len() >= header_len + len {
526                (header_len, len)
527            } else {
528                return Err(Error::EndOfBuffer(Marker::Array32));
529            }
530        }
531        _ => return Err(Error::InvalidArrayType),
532    };
533    Ok((len, header_len))
534}
535
536pub fn read_map_len<B: ByteSlice>(buf: B) -> Result<(usize, usize), Error> {
537    if buf.len() == 0 {
538        return Err(Error::EndOfBuffer(Marker::Map32));
539    }
540
541    let marker = Marker::from(buf[0]);
542    let (len, header_len) = match marker {
543        Marker::FixMap(len) => {
544            let header_len = 1;
545            let len = len as usize;
546            (len, header_len)
547        }
548        #[cfg(feature = "map16")]
549        Marker::Map16 => {
550            let header_len = 3;
551            if buf.len() < header_len {
552                return Err(Error::EndOfBuffer(Marker::Map16));
553            }
554            let len = BigEndian::read_u16(&buf[1..header_len]) as usize;
555            (len, header_len)
556        }
557        #[cfg(feature = "map32")]
558        Marker::Map32 => {
559            let header_len = 5;
560            if buf.len() < header_len {
561                return Err(Error::EndOfBuffer(Marker::Map32));
562            }
563            let len = BigEndian::read_u32(&buf[1..header_len]) as usize;
564            (len, header_len)
565        }
566
567        _ => return Err(Error::InvalidMapType),
568    };
569    if buf.len() >= header_len + len {
570        Ok((len, header_len))
571    } else {
572        Err(Error::EndOfBuffer(Marker::Map32))
573    }
574}
575
576pub fn skip_any<B: ByteSlice>(buf: B) -> Result<((), usize), Error> {
577    if buf.is_empty() {
578        return Ok(((), 0));
579    }
580    let marker = Marker::from_u8(buf[0]);
581    let n = match marker {
582        Marker::FixPos(_) => 1,
583        Marker::U8 => 2,
584        Marker::U16 => 3,
585        Marker::U32 => 5,
586        Marker::U64 => 9,
587        Marker::FixNeg(_) => 1,
588        Marker::I8 => 2,
589        Marker::I16 => 3,
590        Marker::I32 => 5,
591        Marker::I64 => 9,
592
593        Marker::F32 => 5,
594        Marker::F64 => 9,
595
596        Marker::Null | Marker::True | Marker::False | Marker::Reserved => 1,
597
598        Marker::FixStr(n) => n as usize + 1,
599        Marker::Str8 | Marker::Bin8 => {
600            if buf.len() < 2 {
601                return Err(Error::EndOfBuffer(Marker::Str8));
602            }
603            2 + buf[1] as usize
604        }
605        Marker::Str16 | Marker::Bin16 => {
606            if buf.len() < 3 {
607                return Err(Error::EndOfBuffer(Marker::Str16));
608            }
609            3 + BigEndian::read_u16(&buf[1..3]) as usize
610        }
611        Marker::Str32 | Marker::Bin32 => {
612            if buf.len() < 5 {
613                return Err(Error::EndOfBuffer(Marker::Str32));
614            }
615            5 + BigEndian::read_u32(&buf[1..5]) as usize
616        }
617
618        Marker::FixArray(_) | Marker::Array16 | Marker::Array32 => {
619            let (len, n) = read_array_len(&buf[..])?;
620            let mut n = n;
621            for _ in 0..len {
622                //TODO: May overflow stack on embedded systems. Maybe add some kind of safeguard to limit recursion depth
623                n += skip_any(&buf[n..])?.1;
624            }
625            n
626        }
627        Marker::FixMap(_) | Marker::Map16 | Marker::Map32 => {
628            let (len, n) = read_map_len(&buf[..])?;
629            let mut n = n;
630            for _ in 0..len * 2 {
631                //TODO: May overflow stack on embedded systems. Maybe add some kind of safeguard to limit recursion depth
632                n += skip_any(&buf[n..])?.1;
633            }
634            n
635        }
636        Marker::FixExt1 => 3,
637        Marker::FixExt2 => 4,
638        Marker::FixExt4 => 6,
639        Marker::FixExt8 => 10,
640        Marker::FixExt16 => 18,
641        Marker::Ext8 => {
642            if buf.len() < 2 {
643                return Err(Error::EndOfBuffer(Marker::Ext8));
644            }
645            3 + buf[1] as usize
646        }
647        Marker::Ext16 => {
648            if buf.len() < 3 {
649                return Err(Error::EndOfBuffer(Marker::Ext16));
650            }
651            4 + BigEndian::read_u16(&buf[1..3]) as usize
652        }
653        Marker::Ext32 => {
654            if buf.len() < 5 {
655                return Err(Error::EndOfBuffer(Marker::Ext32));
656            }
657            6 + BigEndian::read_u32(&buf[1..5]) as usize
658        }
659    };
660    if buf.len() < n {
661        return Err(Error::EndOfBuffer(Marker::Ext32));
662    }
663    Ok(((), n))
664}