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#[derive(Debug)]
12pub enum Error {
13 EndOfBuffer,
15 OutOfBounds,
21 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")]
36pub 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 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(); let (bin, _rest) = rest.split_at(len).ok().unwrap(); 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(); let (bin, _rest) = rest.split_at(len).ok().unwrap(); 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(); 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(); 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(); let (bin, _rest) = rest.split_at(len).ok().unwrap(); 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 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 = 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 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 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}