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