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#[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(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 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 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)?; 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 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 = 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 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 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}