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