1#![no_std]
2
3#[cfg(feature = "std")]
4extern crate std;
5
6pub const JSON_ATTR_MAX: usize = 31;
7pub const JSON_VAL_MAX: usize = 512;
8
9pub type Result<T> = core::result::Result<T, Error>;
10
11#[derive(Clone, Copy, Debug, Eq, PartialEq)]
12#[repr(i32)]
13pub enum Error {
14 ObStart = 1,
15 AttrStart = 2,
16 BadAttr = 3,
17 AttrLen = 4,
18 NoArray = 5,
19 NoBrak = 6,
20 StrLong = 7,
21 TokLong = 8,
22 BadTrail = 9,
23 ArrayStart = 10,
24 ObjArr = 11,
25 SubTooLong = 12,
26 BadSubTrail = 13,
27 SubType = 14,
28 BadString = 15,
29 CheckFail = 16,
30 NoParStr = 17,
31 BadEnum = 18,
32 QNonString = 19,
33 NonQString = 20,
34 Misc = 21,
35 BadNum = 22,
36 NullPtr = 23,
37 NoCurly = 24,
38 Empty = 25,
39}
40
41impl Error {
42 #[inline]
43 pub const fn message(self) -> &'static str {
44 match self {
45 Error::ObStart => "non-whitespace when expecting object start",
46 Error::AttrStart => "non-whitespace when expecting attribute start",
47 Error::BadAttr => "unknown attribute name",
48 Error::AttrLen => "attribute name too long",
49 Error::NoArray => "saw [ when not expecting array",
50 Error::NoBrak => "array element specified, but no [",
51 Error::StrLong => "string value too long",
52 Error::TokLong => "token value too long",
53 Error::BadTrail => "garbage while expecting comma or } or ]",
54 Error::ArrayStart => "didn't find expected array start",
55 Error::ObjArr => "error while parsing object array",
56 Error::SubTooLong => "too many array elements",
57 Error::BadSubTrail => "garbage while expecting array comma",
58 Error::SubType => "unsupported array element type",
59 Error::BadString => "error while string parsing",
60 Error::CheckFail => "check attribute not matched",
61 Error::NoParStr => "can't support strings in parallel arrays",
62 Error::BadEnum => "invalid enumerated value",
63 Error::QNonString => "saw quoted value when expecting nonstring",
64 Error::NonQString => "didn't see quoted value when expecting string",
65 Error::Misc => "other data conversion error",
66 Error::BadNum => "error while parsing a numerical argument",
67 Error::NullPtr => "unexpected null value or attribute pointer",
68 Error::NoCurly => "object element specified, but no {",
69 Error::Empty => "input was empty or white-space only",
70 }
71 }
72}
73
74impl core::fmt::Display for Error {
75 #[inline]
76 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
77 f.write_str(self.message())
78 }
79}
80
81#[cfg(feature = "std")]
82impl std::error::Error for Error {}
83
84#[inline]
85pub fn error_string(err: Error) -> &'static str {
86 err.message()
87}
88
89#[derive(Clone, Copy)]
90pub struct EnumValue<'a> {
91 pub name: &'a str,
92 pub value: i32,
93}
94
95#[derive(Clone, Copy)]
96pub enum DefaultValue<'a> {
97 None,
98 Integer(i32),
99 UInteger(u32),
100 Short(i16),
101 UShort(u16),
102 Real(f64),
103 Boolean(bool),
104 Character(u8),
105 Check(&'a str),
106}
107
108pub enum Target<'a, T> {
109 One(&'a mut T),
110 Many(&'a mut [T]),
111}
112
113impl<T: Copy> Target<'_, T> {
114 #[inline]
115 fn set(&mut self, offset: usize, value: T) -> Result<()> {
116 match self {
117 Target::One(target) if offset == 0 => {
118 **target = value;
119 Ok(())
120 }
121 Target::Many(targets) => {
122 *targets.get_mut(offset).ok_or(Error::SubTooLong)? = value;
123 Ok(())
124 }
125 Target::One(_) => Ok(()),
126 }
127 }
128}
129
130pub type TargetI32<'a> = Target<'a, i32>;
131pub type TargetU32<'a> = Target<'a, u32>;
132pub type TargetI16<'a> = Target<'a, i16>;
133pub type TargetU16<'a> = Target<'a, u16>;
134pub type TargetF64<'a> = Target<'a, f64>;
135pub type TargetBool<'a> = Target<'a, bool>;
136pub type TargetChar<'a> = Target<'a, u8>;
137
138pub enum AttrKind<'a> {
139 Integer(TargetI32<'a>),
140 UInteger(TargetU32<'a>),
141 Real(TargetF64<'a>),
142 String(&'a mut [u8]),
143 Boolean(TargetBool<'a>),
144 Character(TargetChar<'a>),
145 Time(TargetF64<'a>),
146 Object(&'a mut [Attr<'a>]),
147 Array(Array<'a>),
148 Check(&'a str),
149 Ignore,
150 Short(TargetI16<'a>),
151 UShort(TargetU16<'a>),
152}
153
154pub struct Attr<'a> {
155 pub name: &'a str,
156 pub kind: AttrKind<'a>,
157 pub default: DefaultValue<'a>,
158 pub map: Option<&'a [EnumValue<'a>]>,
159 pub nodefault: bool,
160}
161
162impl<'a> Attr<'a> {
163 #[inline]
164 pub fn integer(name: &'a str, target: &'a mut i32) -> Self {
165 Self::new(name, AttrKind::Integer(TargetI32::One(target)))
166 }
167
168 #[inline]
169 pub fn integers(name: &'a str, target: &'a mut [i32]) -> Self {
170 Self::new(name, AttrKind::Integer(TargetI32::Many(target)))
171 }
172
173 #[inline]
174 pub fn uinteger(name: &'a str, target: &'a mut u32) -> Self {
175 Self::new(name, AttrKind::UInteger(TargetU32::One(target)))
176 }
177
178 #[inline]
179 pub fn uintegers(name: &'a str, target: &'a mut [u32]) -> Self {
180 Self::new(name, AttrKind::UInteger(TargetU32::Many(target)))
181 }
182
183 #[inline]
184 pub fn short(name: &'a str, target: &'a mut i16) -> Self {
185 Self::new(name, AttrKind::Short(TargetI16::One(target)))
186 }
187
188 #[inline]
189 pub fn shorts(name: &'a str, target: &'a mut [i16]) -> Self {
190 Self::new(name, AttrKind::Short(TargetI16::Many(target)))
191 }
192
193 #[inline]
194 pub fn ushort(name: &'a str, target: &'a mut u16) -> Self {
195 Self::new(name, AttrKind::UShort(TargetU16::One(target)))
196 }
197
198 #[inline]
199 pub fn ushorts(name: &'a str, target: &'a mut [u16]) -> Self {
200 Self::new(name, AttrKind::UShort(TargetU16::Many(target)))
201 }
202
203 #[inline]
204 pub fn real(name: &'a str, target: &'a mut f64) -> Self {
205 Self::new(name, AttrKind::Real(TargetF64::One(target)))
206 }
207
208 #[inline]
209 pub fn reals(name: &'a str, target: &'a mut [f64]) -> Self {
210 Self::new(name, AttrKind::Real(TargetF64::Many(target)))
211 }
212
213 #[inline]
214 pub fn string(name: &'a str, target: &'a mut [u8]) -> Self {
215 Self::new(name, AttrKind::String(target))
216 }
217
218 #[inline]
219 pub fn boolean(name: &'a str, target: &'a mut bool) -> Self {
220 Self::new(name, AttrKind::Boolean(TargetBool::One(target)))
221 }
222
223 #[inline]
224 pub fn booleans(name: &'a str, target: &'a mut [bool]) -> Self {
225 Self::new(name, AttrKind::Boolean(TargetBool::Many(target)))
226 }
227
228 #[inline]
229 pub fn character(name: &'a str, target: &'a mut u8) -> Self {
230 Self::new(name, AttrKind::Character(TargetChar::One(target)))
231 }
232
233 #[inline]
234 pub fn characters(name: &'a str, target: &'a mut [u8]) -> Self {
235 Self::new(name, AttrKind::Character(TargetChar::Many(target)))
236 }
237
238 #[inline]
239 pub fn time(name: &'a str, target: &'a mut f64) -> Self {
240 Self::new(name, AttrKind::Time(TargetF64::One(target)))
241 }
242
243 #[inline]
244 pub fn object(name: &'a str, attrs: &'a mut [Attr<'a>]) -> Self {
245 Self::new(name, AttrKind::Object(attrs))
246 }
247
248 #[inline]
249 pub fn array(name: &'a str, array: Array<'a>) -> Self {
250 Self::new(name, AttrKind::Array(array))
251 }
252
253 #[inline]
254 pub fn check(name: &'a str, expected: &'a str) -> Self {
255 let mut attr = Self::new(name, AttrKind::Check(expected));
256 attr.default = DefaultValue::Check(expected);
257 attr
258 }
259
260 #[inline]
261 pub fn ignore_any() -> Self {
262 Self::new("", AttrKind::Ignore)
263 }
264
265 #[inline]
266 pub fn with_default(mut self, default: DefaultValue<'a>) -> Self {
267 self.default = default;
268 self
269 }
270
271 #[inline]
272 pub fn with_map(mut self, map: &'a [EnumValue<'a>]) -> Self {
273 self.map = Some(map);
274 self
275 }
276
277 #[inline]
278 pub fn nodefault(mut self) -> Self {
279 self.nodefault = true;
280 self
281 }
282
283 #[inline]
284 fn new(name: &'a str, kind: AttrKind<'a>) -> Self {
285 Self {
286 name,
287 kind,
288 default: DefaultValue::None,
289 map: None,
290 nodefault: false,
291 }
292 }
293}
294
295pub enum Array<'a> {
296 Strings {
297 store: &'a mut [&'a mut [u8]],
298 count: Option<&'a mut usize>,
299 },
300 Integers {
301 store: &'a mut [i32],
302 count: Option<&'a mut usize>,
303 },
304 UIntegers {
305 store: &'a mut [u32],
306 count: Option<&'a mut usize>,
307 },
308 Shorts {
309 store: &'a mut [i16],
310 count: Option<&'a mut usize>,
311 },
312 UShorts {
313 store: &'a mut [u16],
314 count: Option<&'a mut usize>,
315 },
316 Reals {
317 store: &'a mut [f64],
318 count: Option<&'a mut usize>,
319 },
320 Booleans {
321 store: &'a mut [bool],
322 count: Option<&'a mut usize>,
323 },
324 Objects {
325 attrs: &'a mut [Attr<'a>],
326 maxlen: usize,
327 count: Option<&'a mut usize>,
328 },
329 StructObjects {
330 maxlen: usize,
331 count: Option<&'a mut usize>,
332 parser: &'a mut dyn FnMut(&str, usize) -> Result<usize>,
333 },
334}
335
336#[inline]
337pub fn read_object(input: &str, attrs: &mut [Attr<'_>]) -> Result<usize> {
338 read_object_internal(input, attrs, None, 0)
339}
340
341#[inline]
342pub fn read_array(input: &str, array: &mut Array<'_>) -> Result<usize> {
343 read_array_internal(input, array)
344}
345
346pub fn validate_json(input: &[u8]) -> Result<usize> {
347 let mut validator = JsonValidator {
348 bytes: input,
349 depth: 0,
350 };
351 let end = validator.parse_value(validator.skip_ws(0))?;
352 let end = validator.skip_ws(end);
353 if end == input.len() {
354 Ok(end)
355 } else {
356 Err(Error::BadTrail)
357 }
358}
359
360#[inline]
361pub fn cstr(buf: &[u8]) -> &str {
362 let len = buf.iter().position(|&b| b == 0).unwrap_or(buf.len());
363 core::str::from_utf8(&buf[..len]).unwrap_or("")
364}
365
366struct JsonValidator<'a> {
367 bytes: &'a [u8],
368 depth: usize,
369}
370
371impl JsonValidator<'_> {
372 const MAX_DEPTH: usize = 1024;
373
374 #[inline]
375 fn parse_value(&mut self, i: usize) -> Result<usize> {
376 if i >= self.bytes.len() {
377 return Err(Error::BadTrail);
378 }
379 match self.bytes[i] {
380 b'{' => self.parse_object(i),
381 b'[' => self.parse_array(i),
382 b'"' => self.parse_string(i),
383 b't' => self.parse_literal(i, b"true"),
384 b'f' => self.parse_literal(i, b"false"),
385 b'n' => self.parse_literal(i, b"null"),
386 b'-' | b'0'..=b'9' => self.parse_number(i),
387 _ => Err(Error::BadTrail),
388 }
389 }
390
391 fn parse_object(&mut self, mut i: usize) -> Result<usize> {
392 self.enter()?;
393 i += 1;
394 i = self.skip_ws(i);
395 if i < self.bytes.len() && self.bytes[i] == b'}' {
396 self.leave();
397 return Ok(i + 1);
398 }
399 loop {
400 if i >= self.bytes.len() || self.bytes[i] != b'"' {
401 self.leave();
402 return Err(Error::AttrStart);
403 }
404 i = self.parse_string(i)?;
405 i = self.skip_ws(i);
406 if i >= self.bytes.len() || self.bytes[i] != b':' {
407 self.leave();
408 return Err(Error::BadTrail);
409 }
410 i = self.parse_value(self.skip_ws(i + 1))?;
411 i = self.skip_ws(i);
412 if i >= self.bytes.len() {
413 self.leave();
414 return Err(Error::BadTrail);
415 }
416 match self.bytes[i] {
417 b',' => i = self.skip_ws(i + 1),
418 b'}' => {
419 self.leave();
420 return Ok(i + 1);
421 }
422 _ => {
423 self.leave();
424 return Err(Error::BadTrail);
425 }
426 }
427 }
428 }
429
430 fn parse_array(&mut self, mut i: usize) -> Result<usize> {
431 self.enter()?;
432 i += 1;
433 i = self.skip_ws(i);
434 if i < self.bytes.len() && self.bytes[i] == b']' {
435 self.leave();
436 return Ok(i + 1);
437 }
438 loop {
439 i = self.parse_value(i)?;
440 i = self.skip_ws(i);
441 if i >= self.bytes.len() {
442 self.leave();
443 return Err(Error::BadTrail);
444 }
445 match self.bytes[i] {
446 b',' => i = self.skip_ws(i + 1),
447 b']' => {
448 self.leave();
449 return Ok(i + 1);
450 }
451 _ => {
452 self.leave();
453 return Err(Error::BadTrail);
454 }
455 }
456 }
457 }
458
459 fn parse_string(&self, mut i: usize) -> Result<usize> {
460 i += 1;
461 let mut raw_start = i;
462 while i < self.bytes.len() {
463 match self.bytes[i] {
464 b'"' => {
465 core::str::from_utf8(&self.bytes[raw_start..i])
466 .map_err(|_| Error::BadString)?;
467 return Ok(i + 1);
468 }
469 b'\\' => {
470 core::str::from_utf8(&self.bytes[raw_start..i])
471 .map_err(|_| Error::BadString)?;
472 i += 1;
473 if i >= self.bytes.len() {
474 return Err(Error::BadString);
475 }
476 match self.bytes[i] {
477 b'"' | b'\\' | b'/' | b'b' | b'f' | b'n' | b'r' | b't' => {
478 i += 1;
479 }
480 b'u' => {
481 i += 1;
482 for _ in 0..4 {
483 if i >= self.bytes.len() || hex_val(self.bytes[i]).is_none() {
484 return Err(Error::BadString);
485 }
486 i += 1;
487 }
488 }
489 _ => return Err(Error::BadString),
490 }
491 raw_start = i;
492 }
493 0x00..=0x1f => return Err(Error::BadString),
494 _ => i += 1,
495 }
496 }
497 Err(Error::BadString)
498 }
499
500 #[inline]
501 fn parse_literal(&self, i: usize, literal: &[u8]) -> Result<usize> {
502 if self.bytes[i..].starts_with(literal) {
503 Ok(i + literal.len())
504 } else {
505 Err(Error::BadTrail)
506 }
507 }
508
509 fn parse_number(&self, mut i: usize) -> Result<usize> {
510 if i < self.bytes.len() && self.bytes[i] == b'-' {
511 i += 1;
512 }
513 if i >= self.bytes.len() {
514 return Err(Error::BadNum);
515 }
516 if self.bytes[i] == b'0' {
517 i += 1;
518 if i < self.bytes.len() && self.bytes[i].is_ascii_digit() {
519 return Err(Error::BadNum);
520 }
521 } else if self.bytes[i].is_ascii_digit() {
522 while i < self.bytes.len() && self.bytes[i].is_ascii_digit() {
523 i += 1;
524 }
525 } else {
526 return Err(Error::BadNum);
527 }
528 if i < self.bytes.len() && self.bytes[i] == b'.' {
529 i += 1;
530 let start = i;
531 while i < self.bytes.len() && self.bytes[i].is_ascii_digit() {
532 i += 1;
533 }
534 if i == start {
535 return Err(Error::BadNum);
536 }
537 }
538 if i < self.bytes.len() && matches!(self.bytes[i], b'e' | b'E') {
539 i += 1;
540 if i < self.bytes.len() && matches!(self.bytes[i], b'+' | b'-') {
541 i += 1;
542 }
543 let start = i;
544 while i < self.bytes.len() && self.bytes[i].is_ascii_digit() {
545 i += 1;
546 }
547 if i == start {
548 return Err(Error::BadNum);
549 }
550 }
551 Ok(i)
552 }
553
554 #[inline]
555 fn skip_ws(&self, mut i: usize) -> usize {
556 while i < self.bytes.len() && matches!(self.bytes[i], b' ' | b'\t' | b'\n' | b'\r') {
557 i += 1;
558 }
559 i
560 }
561
562 #[inline]
563 fn enter(&mut self) -> Result<()> {
564 self.depth += 1;
565 if self.depth > Self::MAX_DEPTH {
566 return Err(Error::SubTooLong);
567 }
568 Ok(())
569 }
570
571 #[inline]
572 fn leave(&mut self) {
573 self.depth -= 1;
574 }
575}
576
577fn read_object_internal(
578 input: &str,
579 attrs: &mut [Attr<'_>],
580 parent_is_structobject: Option<bool>,
581 offset: usize,
582) -> Result<usize> {
583 apply_defaults(attrs, parent_is_structobject, offset)?;
584
585 let bytes = input.as_bytes();
586 let mut i = skip_ws(bytes, 0);
587 if i >= bytes.len() {
588 return Err(Error::Empty);
589 }
590 if bytes[i] != b'{' {
591 return Err(Error::ObStart);
592 }
593 i += 1;
594
595 loop {
596 i = skip_ws(bytes, i);
597 if i >= bytes.len() {
598 return Err(Error::AttrStart);
599 }
600 if bytes[i] == b'}' {
601 i += 1;
602 return Ok(skip_ws(bytes, i));
603 }
604 if bytes[i] != b'"' {
605 return Err(Error::AttrStart);
606 }
607 i += 1;
608
609 let mut attr_buf = [0u8; JSON_ATTR_MAX + 1];
610 let attr_len = parse_attr_name(bytes, &mut i, &mut attr_buf)?;
611 let attr_name = core::str::from_utf8(&attr_buf[..attr_len]).map_err(|_| Error::BadAttr)?;
612 let first = find_attr(attrs, attr_name).ok_or(Error::BadAttr)?;
613
614 i = skip_ws(bytes, i);
615 if i < bytes.len() && bytes[i] == b':' {
616 i += 1;
617 }
618 i = skip_ws(bytes, i);
619 if i >= bytes.len() {
620 return Err(Error::BadTrail);
621 }
622
623 if bytes[i] == b'[' {
624 if !matches!(attrs[first].kind, AttrKind::Array(_)) {
625 return Err(Error::NoArray);
626 }
627 let AttrKind::Array(array) = &mut attrs[first].kind else {
628 unreachable!();
629 };
630 i += read_array_internal(&input[i..], array)?;
631 i = skip_ws(bytes, i);
632 } else if matches!(attrs[first].kind, AttrKind::Array(_)) {
633 return Err(Error::NoBrak);
634 } else if bytes[i] == b'{' {
635 if !matches!(attrs[first].kind, AttrKind::Object(_)) {
636 return Err(Error::NoArray);
637 }
638 let AttrKind::Object(child) = &mut attrs[first].kind else {
639 unreachable!();
640 };
641 i += read_object_internal(&input[i..], child, None, 0)?;
642 i = skip_ws(bytes, i);
643 } else if matches!(attrs[first].kind, AttrKind::Object(_)) {
644 return Err(Error::NoCurly);
645 } else {
646 let mut val_buf = [0u8; JSON_VAL_MAX + 1];
647 let quoted = if bytes[i] == b'"' {
648 i += 1;
649 let maxlen = value_max_len(&attrs[first]);
650 parse_string_value(bytes, &mut i, &mut val_buf, maxlen)?;
651 true
652 } else {
653 parse_token_value(bytes, &mut i, &mut val_buf)?;
654 false
655 };
656 let selected = select_attr(attrs, first, attr_name, &val_buf, quoted)?;
657 apply_value(
658 &mut attrs[selected],
659 parent_is_structobject,
660 offset,
661 &val_buf,
662 quoted,
663 )?;
664 i = skip_ws(bytes, i);
665 }
666
667 if i >= bytes.len() {
668 return Err(Error::BadTrail);
669 }
670 if bytes[i] == b',' {
671 i += 1;
672 } else if bytes[i] == b'}' {
673 i += 1;
674 return Ok(skip_ws(bytes, i));
675 } else {
676 return Err(Error::BadTrail);
677 }
678 }
679}
680
681fn read_array_internal(input: &str, array: &mut Array<'_>) -> Result<usize> {
682 let bytes = input.as_bytes();
683 let mut i = skip_ws(bytes, 0);
684 if i >= bytes.len() || bytes[i] != b'[' {
685 return Err(Error::ArrayStart);
686 }
687 i += 1;
688 i = skip_ws(bytes, i);
689 if i < bytes.len() && bytes[i] == b']' {
690 set_array_count(array, 0);
691 return Ok(skip_ws(bytes, i + 1));
692 }
693
694 let maxlen = array_maxlen(array);
695 let mut count = 0usize;
696 while count < maxlen {
697 i = skip_ws(bytes, i);
698 match array {
699 Array::Strings { store, .. } => {
700 if i >= bytes.len() || bytes[i] != b'"' {
701 return Err(Error::BadString);
702 }
703 i += 1;
704 parse_string_value(
705 bytes,
706 &mut i,
707 store[count],
708 store[count].len().saturating_sub(1),
709 )?;
710 }
711 Array::Integers { store, .. } => {
712 let (v, end) = parse_i32_at(bytes, i)?;
713 store[count] = v;
714 i = end;
715 }
716 Array::UIntegers { store, .. } => {
717 let (v, end) = parse_u32_at(bytes, i)?;
718 store[count] = v;
719 i = end;
720 }
721 Array::Shorts { store, .. } => {
722 let (v, end) = parse_i16_at(bytes, i)?;
723 store[count] = v;
724 i = end;
725 }
726 Array::UShorts { store, .. } => {
727 let (v, end) = parse_u16_at(bytes, i)?;
728 store[count] = v;
729 i = end;
730 }
731 Array::Reals { store, .. } => {
732 let (v, end) = parse_f64_at(bytes, i)?;
733 store[count] = v;
734 i = end;
735 }
736 Array::Booleans { store, .. } => {
737 let (v, end) = parse_bool_at(bytes, i)?;
738 store[count] = v;
739 i = end;
740 }
741 Array::Objects { attrs, .. } => {
742 i += read_object_internal(&input[i..], attrs, Some(false), count)?;
743 }
744 Array::StructObjects { parser, .. } => {
745 i += parser(&input[i..], count)?;
746 }
747 }
748 count += 1;
749 i = skip_ws(bytes, i);
750 if i < bytes.len() && bytes[i] == b']' {
751 set_array_count(array, count);
752 return Ok(skip_ws(bytes, i + 1));
753 }
754 if i < bytes.len() && bytes[i] == b',' {
755 i += 1;
756 } else {
757 return Err(Error::BadSubTrail);
758 }
759 }
760
761 Err(Error::SubTooLong)
762}
763
764fn apply_defaults(
765 attrs: &mut [Attr<'_>],
766 parent_is_structobject: Option<bool>,
767 offset: usize,
768) -> Result<()> {
769 for attr in attrs {
770 if attr.nodefault {
771 continue;
772 }
773 match attr.default {
774 DefaultValue::None => {
775 if let AttrKind::String(buf) = &mut attr.kind {
776 if matches!(parent_is_structobject, Some(false)) && offset > 0 {
777 return Err(Error::NoParStr);
778 }
779 clear_cbuf(buf);
780 }
781 }
782 DefaultValue::Integer(v) => set_i32(&mut attr.kind, offset, v)?,
783 DefaultValue::UInteger(v) => set_u32(&mut attr.kind, offset, v)?,
784 DefaultValue::Short(v) => set_i16(&mut attr.kind, offset, v)?,
785 DefaultValue::UShort(v) => set_u16(&mut attr.kind, offset, v)?,
786 DefaultValue::Real(v) => set_f64(&mut attr.kind, offset, v)?,
787 DefaultValue::Boolean(v) => set_bool(&mut attr.kind, offset, v)?,
788 DefaultValue::Character(v) => set_char(&mut attr.kind, offset, v)?,
789 DefaultValue::Check(_) => {}
790 }
791 }
792 Ok(())
793}
794
795fn parse_attr_name(
796 bytes: &[u8],
797 i: &mut usize,
798 out: &mut [u8; JSON_ATTR_MAX + 1],
799) -> Result<usize> {
800 let mut len = 0usize;
801 while *i < bytes.len() {
802 let b = bytes[*i];
803 *i += 1;
804 if b == b'"' {
805 return Ok(len);
806 }
807 if len >= JSON_ATTR_MAX {
808 return Err(Error::AttrLen);
809 }
810 out[len] = b;
811 len += 1;
812 }
813 Err(Error::BadString)
814}
815
816fn parse_string_value(
817 bytes: &[u8],
818 i: &mut usize,
819 out: &mut [u8],
820 max_content_len: usize,
821) -> Result<usize> {
822 clear_cbuf(out);
823 let mut len = 0usize;
824 while *i < bytes.len() {
825 let b = bytes[*i];
826 *i += 1;
827 let outb = if b == b'\\' {
828 if *i >= bytes.len() {
829 return Err(Error::BadString);
830 }
831 let e = bytes[*i];
832 *i += 1;
833 match e {
834 b'b' => 8,
835 b'f' => 12,
836 b'n' => b'\n',
837 b'r' => b'\r',
838 b't' => b'\t',
839 b'u' => {
840 if *i + 4 > bytes.len() {
841 return Err(Error::BadString);
842 }
843 let mut v = 0u32;
844 for _ in 0..4 {
845 let Some(d) = hex_val(bytes[*i]) else {
846 return Err(Error::BadString);
847 };
848 v = (v << 4) | d as u32;
849 *i += 1;
850 }
851 v as u8
852 }
853 other => other,
854 }
855 } else if b == b'"' {
856 if len < out.len() {
857 out[len] = 0;
858 }
859 return Ok(len);
860 } else {
861 b
862 };
863 if len >= JSON_VAL_MAX || len >= max_content_len || len + 1 > out.len() {
864 return Err(Error::StrLong);
865 }
866 out[len] = outb;
867 len += 1;
868 }
869 Err(Error::BadString)
870}
871
872fn parse_token_value(
873 bytes: &[u8],
874 i: &mut usize,
875 out: &mut [u8; JSON_VAL_MAX + 1],
876) -> Result<usize> {
877 let mut len = 0usize;
878 while *i < bytes.len() {
879 let b = bytes[*i];
880 if is_ws(b) || b == b',' || b == b'}' || b == b']' {
881 out[len] = 0;
882 return Ok(len);
883 }
884 if len >= JSON_VAL_MAX {
885 return Err(Error::TokLong);
886 }
887 out[len] = b;
888 len += 1;
889 *i += 1;
890 }
891 out[len] = 0;
892 Ok(len)
893}
894
895fn find_attr(attrs: &[Attr<'_>], name: &str) -> Option<usize> {
896 let mut ignore = None;
897 for (idx, attr) in attrs.iter().enumerate() {
898 if attr.name == name {
899 return Some(idx);
900 }
901 if attr.name.is_empty() && matches!(attr.kind, AttrKind::Ignore) {
902 ignore = Some(idx);
903 }
904 }
905 ignore
906}
907
908fn select_attr(
909 attrs: &[Attr<'_>],
910 first: usize,
911 name: &str,
912 val: &[u8; JSON_VAL_MAX + 1],
913 quoted: bool,
914) -> Result<usize> {
915 let mut idx = first;
916 loop {
917 if value_fits_attr(&attrs[idx], val, quoted) {
918 break;
919 }
920 if idx + 1 >= attrs.len() || attrs[idx + 1].name != name {
921 break;
922 }
923 idx += 1;
924 }
925
926 let attr = &attrs[idx];
927 if quoted
928 && !matches!(
929 attr.kind,
930 AttrKind::String(_)
931 | AttrKind::Character(_)
932 | AttrKind::Check(_)
933 | AttrKind::Time(_)
934 | AttrKind::Ignore
935 )
936 && attr.map.is_none()
937 {
938 return Err(Error::QNonString);
939 }
940 if !quoted
941 && (matches!(
942 attr.kind,
943 AttrKind::String(_) | AttrKind::Check(_) | AttrKind::Time(_)
944 ) || attr.map.is_some())
945 {
946 return Err(Error::NonQString);
947 }
948 Ok(idx)
949}
950
951fn value_fits_attr(attr: &Attr<'_>, val: &[u8; JSON_VAL_MAX + 1], quoted: bool) -> bool {
952 if quoted {
953 return matches!(attr.kind, AttrKind::String(_) | AttrKind::Time(_));
954 }
955 if token_eq(val, b"true") || token_eq(val, b"false") {
956 return matches!(attr.kind, AttrKind::Boolean(_));
957 }
958 if json_number_is_integer(val) {
959 return matches!(
960 attr.kind,
961 AttrKind::Integer(_) | AttrKind::UInteger(_) | AttrKind::Short(_) | AttrKind::UShort(_)
962 );
963 }
964 if json_number_is_real(val) {
965 return matches!(attr.kind, AttrKind::Real(_));
966 }
967 false
968}
969
970fn apply_value(
971 attr: &mut Attr<'_>,
972 parent_is_structobject: Option<bool>,
973 offset: usize,
974 val: &[u8; JSON_VAL_MAX + 1],
975 _quoted: bool,
976) -> Result<()> {
977 let mut mapped_buf = [0u8; JSON_VAL_MAX + 1];
978 let val = if let Some(map) = attr.map {
979 let s = token_str(val)?;
980 let mut found = None;
981 for item in map {
982 if item.name == s {
983 found = Some(item.value);
984 break;
985 }
986 }
987 let Some(found) = found else {
988 return Err(Error::BadEnum);
989 };
990 write_i32_token(found, &mut mapped_buf);
991 &mapped_buf
992 } else {
993 val
994 };
995
996 match &mut attr.kind {
997 AttrKind::Integer(_) => {
998 let v = parse_i32_token(val)?;
999 set_i32(&mut attr.kind, offset, v)
1000 }
1001 AttrKind::UInteger(_) => {
1002 let v = parse_u32_token(val)?;
1003 set_u32(&mut attr.kind, offset, v)
1004 }
1005 AttrKind::Short(_) => {
1006 let v = parse_i16_token(val)?;
1007 set_i16(&mut attr.kind, offset, v)
1008 }
1009 AttrKind::UShort(_) => {
1010 let v = parse_u16_token(val)?;
1011 set_u16(&mut attr.kind, offset, v)
1012 }
1013 AttrKind::Real(_) => {
1014 let v = parse_f64_token(val)?;
1015 set_f64(&mut attr.kind, offset, v)
1016 }
1017 AttrKind::String(buf) => {
1018 if matches!(parent_is_structobject, Some(false)) && offset > 0 {
1019 return Err(Error::NoParStr);
1020 }
1021 copy_cbuf(buf, val);
1022 Ok(())
1023 }
1024 AttrKind::Boolean(_) => {
1025 let v = if token_eq(val, b"true") {
1026 true
1027 } else if token_eq(val, b"false") {
1028 false
1029 } else {
1030 parse_i64_token(val)? != 0
1031 };
1032 set_bool(&mut attr.kind, offset, v)
1033 }
1034 AttrKind::Character(_) => {
1035 let len = token_len(val);
1036 if len > 1 {
1037 return Err(Error::StrLong);
1038 }
1039 set_char(&mut attr.kind, offset, if len == 0 { 0 } else { val[0] })
1040 }
1041 AttrKind::Check(expected) => {
1042 if token_str(val)? == *expected {
1043 Ok(())
1044 } else {
1045 Err(Error::CheckFail)
1046 }
1047 }
1048 AttrKind::Ignore => Ok(()),
1049 AttrKind::Time(_) => Ok(()),
1050 AttrKind::Object(_) | AttrKind::Array(_) => Ok(()),
1051 }
1052}
1053
1054#[inline]
1055fn set_i32(kind: &mut AttrKind<'_>, offset: usize, value: i32) -> Result<()> {
1056 if let AttrKind::Integer(target) = kind {
1057 target.set(offset, value)?;
1058 }
1059 Ok(())
1060}
1061
1062#[inline]
1063fn set_u32(kind: &mut AttrKind<'_>, offset: usize, value: u32) -> Result<()> {
1064 if let AttrKind::UInteger(target) = kind {
1065 target.set(offset, value)?;
1066 }
1067 Ok(())
1068}
1069
1070#[inline]
1071fn set_i16(kind: &mut AttrKind<'_>, offset: usize, value: i16) -> Result<()> {
1072 if let AttrKind::Short(target) = kind {
1073 target.set(offset, value)?;
1074 }
1075 Ok(())
1076}
1077
1078#[inline]
1079fn set_u16(kind: &mut AttrKind<'_>, offset: usize, value: u16) -> Result<()> {
1080 if let AttrKind::UShort(target) = kind {
1081 target.set(offset, value)?;
1082 }
1083 Ok(())
1084}
1085
1086#[inline]
1087fn set_f64(kind: &mut AttrKind<'_>, offset: usize, value: f64) -> Result<()> {
1088 match kind {
1089 AttrKind::Real(target) | AttrKind::Time(target) => target.set(offset, value)?,
1090 _ => {}
1091 }
1092 Ok(())
1093}
1094
1095#[inline]
1096fn set_bool(kind: &mut AttrKind<'_>, offset: usize, value: bool) -> Result<()> {
1097 if let AttrKind::Boolean(target) = kind {
1098 target.set(offset, value)?;
1099 }
1100 Ok(())
1101}
1102
1103#[inline]
1104fn set_char(kind: &mut AttrKind<'_>, offset: usize, value: u8) -> Result<()> {
1105 if let AttrKind::Character(target) = kind {
1106 target.set(offset, value)?;
1107 }
1108 Ok(())
1109}
1110
1111#[inline]
1112fn value_max_len(attr: &Attr<'_>) -> usize {
1113 match &attr.kind {
1114 AttrKind::String(buf) => buf.len().saturating_sub(1),
1115 AttrKind::Check(expected) => expected.len(),
1116 AttrKind::Time(_) | AttrKind::Ignore => JSON_VAL_MAX,
1117 _ if attr.map.is_some() => JSON_VAL_MAX,
1118 _ => JSON_VAL_MAX,
1119 }
1120}
1121
1122#[inline]
1123fn array_maxlen(array: &Array<'_>) -> usize {
1124 match array {
1125 Array::Strings { store, .. } => store.len(),
1126 Array::Integers { store, .. } => store.len(),
1127 Array::UIntegers { store, .. } => store.len(),
1128 Array::Shorts { store, .. } => store.len(),
1129 Array::UShorts { store, .. } => store.len(),
1130 Array::Reals { store, .. } => store.len(),
1131 Array::Booleans { store, .. } => store.len(),
1132 Array::Objects { maxlen, .. } => *maxlen,
1133 Array::StructObjects { maxlen, .. } => *maxlen,
1134 }
1135}
1136
1137#[inline]
1138fn set_array_count(array: &mut Array<'_>, value: usize) {
1139 match array {
1140 Array::Strings { count, .. }
1141 | Array::Integers { count, .. }
1142 | Array::UIntegers { count, .. }
1143 | Array::Shorts { count, .. }
1144 | Array::UShorts { count, .. }
1145 | Array::Reals { count, .. }
1146 | Array::Booleans { count, .. }
1147 | Array::Objects { count, .. }
1148 | Array::StructObjects { count, .. } => {
1149 if let Some(count) = count {
1150 **count = value;
1151 }
1152 }
1153 }
1154}
1155
1156#[inline]
1157fn skip_ws(bytes: &[u8], mut i: usize) -> usize {
1158 while i < bytes.len() && is_ws(bytes[i]) {
1159 i += 1;
1160 }
1161 i
1162}
1163
1164#[inline]
1165fn is_ws(b: u8) -> bool {
1166 matches!(b, b' ' | b'\t' | b'\n' | b'\r' | 0x0c | 0x0b)
1167}
1168
1169#[inline]
1170fn clear_cbuf(buf: &mut [u8]) {
1171 for b in buf {
1172 *b = 0;
1173 }
1174}
1175
1176#[inline]
1177fn copy_cbuf(out: &mut [u8], val: &[u8; JSON_VAL_MAX + 1]) {
1178 clear_cbuf(out);
1179 if out.is_empty() {
1180 return;
1181 }
1182 let n = core::cmp::min(token_len(val), out.len() - 1);
1183 out[..n].copy_from_slice(&val[..n]);
1184}
1185
1186#[inline]
1187fn token_len(token: &[u8]) -> usize {
1188 token.iter().position(|&b| b == 0).unwrap_or(token.len())
1189}
1190
1191#[inline]
1192fn token_str(token: &[u8]) -> Result<&str> {
1193 core::str::from_utf8(&token[..token_len(token)]).map_err(|_| Error::BadString)
1194}
1195
1196#[inline]
1197fn token_eq(token: &[u8], expected: &[u8]) -> bool {
1198 &token[..token_len(token)] == expected
1199}
1200
1201#[inline]
1202fn hex_val(b: u8) -> Option<u8> {
1203 match b {
1204 b'0'..=b'9' => Some(b - b'0'),
1205 b'a'..=b'f' => Some(b - b'a' + 10),
1206 b'A'..=b'F' => Some(b - b'A' + 10),
1207 _ => None,
1208 }
1209}
1210
1211#[inline]
1212fn parse_i32_at(bytes: &[u8], start: usize) -> Result<(i32, usize)> {
1213 let end = number_end(bytes, start)?;
1214 Ok((parse_i32_bytes(&bytes[start..end])?, end))
1215}
1216
1217#[inline]
1218fn parse_u32_at(bytes: &[u8], start: usize) -> Result<(u32, usize)> {
1219 let end = number_end(bytes, start)?;
1220 Ok((parse_u32_bytes(&bytes[start..end])?, end))
1221}
1222
1223#[inline]
1224fn parse_i16_at(bytes: &[u8], start: usize) -> Result<(i16, usize)> {
1225 let end = number_end(bytes, start)?;
1226 let v = parse_i64_bytes(&bytes[start..end])?;
1227 if v < i16::MIN as i64 || v > i16::MAX as i64 {
1228 return Err(Error::BadNum);
1229 }
1230 Ok((v as i16, end))
1231}
1232
1233#[inline]
1234fn parse_u16_at(bytes: &[u8], start: usize) -> Result<(u16, usize)> {
1235 let end = number_end(bytes, start)?;
1236 let v = parse_u64_bytes(&bytes[start..end])?;
1237 if v > u16::MAX as u64 {
1238 return Err(Error::BadNum);
1239 }
1240 Ok((v as u16, end))
1241}
1242
1243#[inline]
1244fn parse_f64_at(bytes: &[u8], start: usize) -> Result<(f64, usize)> {
1245 let end = number_end(bytes, start)?;
1246 Ok((parse_f64_bytes(&bytes[start..end])?, end))
1247}
1248
1249#[inline]
1250fn parse_bool_at(bytes: &[u8], start: usize) -> Result<(bool, usize)> {
1251 if bytes[start..].starts_with(b"true") {
1252 Ok((true, start + 4))
1253 } else if bytes[start..].starts_with(b"false") {
1254 Ok((false, start + 5))
1255 } else {
1256 let (v, end) = parse_i32_at(bytes, start)?;
1257 Ok((v != 0, end))
1258 }
1259}
1260
1261fn number_end(bytes: &[u8], mut i: usize) -> Result<usize> {
1262 let start = i;
1263 if i < bytes.len() && bytes[i] == b'-' {
1264 i += 1;
1265 }
1266 let mut saw_digit = false;
1267 while i < bytes.len() && bytes[i].is_ascii_digit() {
1268 saw_digit = true;
1269 i += 1;
1270 }
1271 if i < bytes.len() && bytes[i] == b'.' {
1272 i += 1;
1273 while i < bytes.len() && bytes[i].is_ascii_digit() {
1274 saw_digit = true;
1275 i += 1;
1276 }
1277 }
1278 if i < bytes.len() && matches!(bytes[i], b'e' | b'E') {
1279 i += 1;
1280 if i < bytes.len() && matches!(bytes[i], b'+' | b'-') {
1281 i += 1;
1282 }
1283 let exp_start = i;
1284 while i < bytes.len() && bytes[i].is_ascii_digit() {
1285 i += 1;
1286 }
1287 if i == exp_start {
1288 return Err(Error::BadNum);
1289 }
1290 }
1291 if !saw_digit || i == start {
1292 Err(Error::BadNum)
1293 } else {
1294 Ok(i)
1295 }
1296}
1297
1298#[inline]
1299fn parse_i32_token(token: &[u8]) -> Result<i32> {
1300 parse_i32_bytes(&token[..token_len(token)])
1301}
1302
1303#[inline]
1304fn parse_u32_token(token: &[u8]) -> Result<u32> {
1305 parse_u32_bytes(&token[..token_len(token)])
1306}
1307
1308#[inline]
1309fn parse_i16_token(token: &[u8]) -> Result<i16> {
1310 let v = parse_i64_token(token)?;
1311 if v < i16::MIN as i64 || v > i16::MAX as i64 {
1312 return Err(Error::BadNum);
1313 }
1314 Ok(v as i16)
1315}
1316
1317#[inline]
1318fn parse_u16_token(token: &[u8]) -> Result<u16> {
1319 let v = parse_u64_bytes(&token[..token_len(token)])?;
1320 if v > u16::MAX as u64 {
1321 return Err(Error::BadNum);
1322 }
1323 Ok(v as u16)
1324}
1325
1326#[inline]
1327fn parse_i64_token(token: &[u8]) -> Result<i64> {
1328 parse_i64_bytes(&token[..token_len(token)])
1329}
1330
1331#[inline]
1332fn parse_f64_token(token: &[u8]) -> Result<f64> {
1333 parse_f64_bytes(&token[..token_len(token)])
1334}
1335
1336#[inline]
1337fn parse_i32_bytes(bytes: &[u8]) -> Result<i32> {
1338 let v = parse_i64_bytes(bytes)?;
1339 if v < i32::MIN as i64 || v > i32::MAX as i64 {
1340 return Err(Error::BadNum);
1341 }
1342 Ok(v as i32)
1343}
1344
1345#[inline]
1346fn parse_u32_bytes(bytes: &[u8]) -> Result<u32> {
1347 let v = parse_u64_bytes(bytes)?;
1348 if v > u32::MAX as u64 {
1349 return Err(Error::BadNum);
1350 }
1351 Ok(v as u32)
1352}
1353
1354fn parse_i64_bytes(bytes: &[u8]) -> Result<i64> {
1355 let mut i = 0usize;
1356 let neg = bytes.first() == Some(&b'-');
1357 if neg {
1358 i = 1;
1359 }
1360 if i >= bytes.len() || bytes[i] == b'+' {
1361 return Err(Error::BadNum);
1362 }
1363 let mut v: i64 = 0;
1364 while i < bytes.len() {
1365 let b = bytes[i];
1366 if !b.is_ascii_digit() {
1367 return Err(Error::BadNum);
1368 }
1369 v = v.checked_mul(10).ok_or(Error::BadNum)?;
1370 v = v.checked_add((b - b'0') as i64).ok_or(Error::BadNum)?;
1371 i += 1;
1372 }
1373 if neg {
1374 v.checked_neg().ok_or(Error::BadNum)
1375 } else {
1376 Ok(v)
1377 }
1378}
1379
1380fn parse_u64_bytes(bytes: &[u8]) -> Result<u64> {
1381 if bytes.is_empty() || bytes[0] == b'-' || bytes[0] == b'+' {
1382 return Err(Error::BadNum);
1383 }
1384 let mut v: u64 = 0;
1385 for &b in bytes {
1386 if !b.is_ascii_digit() {
1387 return Err(Error::BadNum);
1388 }
1389 v = v.checked_mul(10).ok_or(Error::BadNum)?;
1390 v = v.checked_add((b - b'0') as u64).ok_or(Error::BadNum)?;
1391 }
1392 Ok(v)
1393}
1394
1395fn parse_f64_bytes(bytes: &[u8]) -> Result<f64> {
1396 if bytes.is_empty() {
1397 return Err(Error::BadNum);
1398 }
1399 let mut i = 0usize;
1400 let neg = bytes[i] == b'-';
1401 if neg {
1402 i += 1;
1403 }
1404 if i >= bytes.len() {
1405 return Err(Error::BadNum);
1406 }
1407 let mut value = 0f64;
1408 let int_start = i;
1409 if bytes[i] == b'0' {
1410 i += 1;
1411 if i < bytes.len() && bytes[i].is_ascii_digit() {
1412 return Err(Error::BadNum);
1413 }
1414 } else {
1415 while i < bytes.len() && bytes[i].is_ascii_digit() {
1416 value = value * 10.0 + (bytes[i] - b'0') as f64;
1417 i += 1;
1418 }
1419 }
1420 if i == int_start {
1421 return Err(Error::BadNum);
1422 }
1423 if i < bytes.len() && bytes[i] == b'.' {
1424 i += 1;
1425 let frac_start = i;
1426 let mut scale = 0.1f64;
1427 while i < bytes.len() && bytes[i].is_ascii_digit() {
1428 value += (bytes[i] - b'0') as f64 * scale;
1429 scale *= 0.1;
1430 i += 1;
1431 }
1432 if i == frac_start {
1433 return Err(Error::BadNum);
1434 }
1435 }
1436 if i < bytes.len() && matches!(bytes[i], b'e' | b'E') {
1437 i += 1;
1438 let exp_neg = if i < bytes.len() && matches!(bytes[i], b'+' | b'-') {
1439 let n = bytes[i] == b'-';
1440 i += 1;
1441 n
1442 } else {
1443 false
1444 };
1445 let exp_start = i;
1446 let mut exp = 0i32;
1447 while i < bytes.len() && bytes[i].is_ascii_digit() {
1448 exp = exp
1449 .saturating_mul(10)
1450 .saturating_add((bytes[i] - b'0') as i32);
1451 i += 1;
1452 }
1453 if i == exp_start {
1454 return Err(Error::BadNum);
1455 }
1456 value *= pow10(if exp_neg { -exp } else { exp });
1457 }
1458 if i != bytes.len() {
1459 return Err(Error::BadNum);
1460 }
1461 Ok(if neg { -value } else { value })
1462}
1463
1464#[inline]
1465fn pow10(exp: i32) -> f64 {
1466 let mut n = if exp < 0 { -exp } else { exp };
1467 let mut base = 10.0f64;
1468 let mut result = 1.0f64;
1469 while n > 0 {
1470 if n & 1 == 1 {
1471 result *= base;
1472 }
1473 base *= base;
1474 n >>= 1;
1475 }
1476 if exp < 0 { 1.0 / result } else { result }
1477}
1478
1479#[inline]
1480fn json_number_is_integer(token: &[u8]) -> bool {
1481 let bytes = &token[..token_len(token)];
1482 match_json_number(bytes).is_some_and(|is_integer| is_integer)
1483}
1484
1485#[inline]
1486fn json_number_is_real(token: &[u8]) -> bool {
1487 let bytes = &token[..token_len(token)];
1488 match_json_number(bytes).is_some_and(|is_integer| !is_integer)
1489}
1490
1491fn match_json_number(bytes: &[u8]) -> Option<bool> {
1492 if bytes.is_empty() {
1493 return None;
1494 }
1495 let mut i = 0usize;
1496 let mut saw_fraction = false;
1497 let mut saw_exponent = false;
1498 if bytes[i] == b'-' {
1499 i += 1;
1500 }
1501 if i >= bytes.len() || !bytes[i].is_ascii_digit() {
1502 return None;
1503 }
1504 if bytes[i] == b'0' {
1505 i += 1;
1506 if i < bytes.len() && bytes[i].is_ascii_digit() {
1507 return None;
1508 }
1509 } else {
1510 while i < bytes.len() && bytes[i].is_ascii_digit() {
1511 i += 1;
1512 }
1513 }
1514 if i < bytes.len() && bytes[i] == b'.' {
1515 saw_fraction = true;
1516 i += 1;
1517 if i >= bytes.len() || !bytes[i].is_ascii_digit() {
1518 return None;
1519 }
1520 while i < bytes.len() && bytes[i].is_ascii_digit() {
1521 i += 1;
1522 }
1523 }
1524 if i < bytes.len() && matches!(bytes[i], b'e' | b'E') {
1525 saw_exponent = true;
1526 i += 1;
1527 if i < bytes.len() && matches!(bytes[i], b'+' | b'-') {
1528 i += 1;
1529 }
1530 if i >= bytes.len() || !bytes[i].is_ascii_digit() {
1531 return None;
1532 }
1533 while i < bytes.len() && bytes[i].is_ascii_digit() {
1534 i += 1;
1535 }
1536 }
1537 if i == bytes.len() {
1538 Some(!(saw_fraction || saw_exponent))
1539 } else {
1540 None
1541 }
1542}
1543
1544fn write_i32_token(mut value: i32, out: &mut [u8; JSON_VAL_MAX + 1]) {
1545 clear_cbuf(out);
1546 if value == 0 {
1547 out[0] = b'0';
1548 return;
1549 }
1550 let mut tmp = [0u8; 12];
1551 let neg = value < 0;
1552 let mut i = tmp.len();
1553 while value != 0 {
1554 let digit = (value % 10).unsigned_abs() as u8;
1555 i -= 1;
1556 tmp[i] = b'0' + digit;
1557 value /= 10;
1558 }
1559 if neg {
1560 i -= 1;
1561 tmp[i] = b'-';
1562 }
1563 let n = tmp.len() - i;
1564 out[..n].copy_from_slice(&tmp[i..]);
1565}
1566
1567#[cfg(test)]
1568#[allow(clippy::drop_non_drop)]
1569mod tests {
1570 use super::*;
1571
1572 #[test]
1573 fn parses_basic_object() {
1574 let mut count = 0;
1575 let mut flag1 = false;
1576 let mut flag2 = true;
1577 let mut attrs = [
1578 Attr::integer("count", &mut count),
1579 Attr::boolean("flag1", &mut flag1),
1580 Attr::boolean("flag2", &mut flag2),
1581 ];
1582
1583 let end = read_object(r#"{"flag2":false,"count":7,"flag1":true}"#, &mut attrs).unwrap();
1584 drop(attrs);
1585 assert_eq!(end, 38);
1586 assert_eq!(count, 7);
1587 assert!(flag1);
1588 assert!(!flag2);
1589 }
1590
1591 #[test]
1592 fn parses_object_array_into_parallel_slices() {
1593 let mut prn = [0; 4];
1594 let mut el = [0; 4];
1595 let mut used = [false; 4];
1596 let mut count = 0;
1597 let mut sat_attrs = [
1598 Attr::integers("PRN", &mut prn),
1599 Attr::integers("el", &mut el),
1600 Attr::booleans("used", &mut used),
1601 ];
1602 let mut attrs = [Attr::array(
1603 "satellites",
1604 Array::Objects {
1605 attrs: &mut sat_attrs,
1606 maxlen: 4,
1607 count: Some(&mut count),
1608 },
1609 )];
1610
1611 read_object(
1612 r#"{"satellites":[{"PRN":10,"el":45,"used":true},{"PRN":21,"el":10,"used":false}]}"#,
1613 &mut attrs,
1614 )
1615 .unwrap();
1616 drop(attrs);
1617 assert_eq!(count, 2);
1618 assert_eq!(prn[..2], [10, 21]);
1619 assert_eq!(el[..2], [45, 10]);
1620 assert_eq!(used[..2], [true, false]);
1621 }
1622
1623 #[test]
1624 fn parses_concatenated_objects() {
1625 let mut flag = false;
1626 let input = r#"{"flag":true} {"flag":0}"#;
1627 let mut attrs = [Attr::boolean("flag", &mut flag)];
1628 let end = read_object(input, &mut attrs).unwrap();
1629 assert_eq!(end, 14);
1630 read_object(&input[end..], &mut attrs).unwrap();
1631 drop(attrs);
1632 assert!(!flag);
1633 }
1634
1635 #[test]
1636 fn applies_defaults_for_omitted_fields() {
1637 let mut flag1 = false;
1638 let mut flag2 = true;
1639 let mut dftint = 0;
1640 let mut dftuint = 0;
1641 let mut dftshort = 0;
1642 let mut dftushort = 0;
1643 let mut dftreal = 0.0;
1644 let mut dftchar = 0;
1645 let mut attrs = [
1646 Attr::integer("dftint", &mut dftint).with_default(DefaultValue::Integer(-5)),
1647 Attr::uinteger("dftuint", &mut dftuint).with_default(DefaultValue::UInteger(10)),
1648 Attr::short("dftshort", &mut dftshort).with_default(DefaultValue::Short(-12)),
1649 Attr::ushort("dftushort", &mut dftushort).with_default(DefaultValue::UShort(12)),
1650 Attr::real("dftreal", &mut dftreal).with_default(DefaultValue::Real(23.17)),
1651 Attr::character("dftchar", &mut dftchar).with_default(DefaultValue::Character(b'X')),
1652 Attr::boolean("flag1", &mut flag1),
1653 Attr::boolean("flag2", &mut flag2),
1654 ];
1655
1656 read_object(r#"{"flag1":true,"flag2":false}"#, &mut attrs).unwrap();
1657 drop(attrs);
1658 assert_eq!(dftint, -5);
1659 assert_eq!(dftuint, 10);
1660 assert_eq!(dftshort, -12);
1661 assert_eq!(dftushort, 12);
1662 assert_eq!(dftreal, 23.17);
1663 assert_eq!(dftchar, b'X');
1664 assert!(flag1);
1665 assert!(!flag2);
1666 }
1667
1668 #[test]
1669 fn nodefault_leaves_existing_value_untouched() {
1670 let mut count = 99;
1671 let mut attrs = [Attr::integer("count", &mut count)
1672 .with_default(DefaultValue::Integer(-1))
1673 .nodefault()];
1674
1675 read_object(r#"{}"#, &mut attrs).unwrap();
1676 drop(attrs);
1677 assert_eq!(count, 99);
1678 }
1679
1680 #[test]
1681 fn parses_fixed_string_buffer_and_escapes() {
1682 let mut name = [b'!'; 16];
1683 let mut attrs = [Attr::string("name", &mut name)];
1684
1685 read_object(r#"{"name":"A\n\u0042\/\""}"#, &mut attrs).unwrap();
1686 drop(attrs);
1687 assert_eq!(cstr(&name), "A\nB/\"");
1688 assert_eq!(name[6], 0);
1689 }
1690
1691 #[test]
1692 fn rejects_string_that_would_overflow_destination() {
1693 let mut name = [0; 4];
1694 let mut attrs = [Attr::string("name", &mut name)];
1695
1696 let err = read_object(r#"{"name":"abcd"}"#, &mut attrs).unwrap_err();
1697 drop(attrs);
1698 assert_eq!(err, Error::StrLong);
1699 assert_eq!(cstr(&name), "");
1700 }
1701
1702 #[test]
1703 fn parses_character_field() {
1704 let mut ch = 0;
1705 let mut attrs = [Attr::character("parity", &mut ch)];
1706
1707 read_object(r#"{"parity":"N"}"#, &mut attrs).unwrap();
1708 drop(attrs);
1709 assert_eq!(ch, b'N');
1710 }
1711
1712 #[test]
1713 fn rejects_multi_byte_character_field() {
1714 let mut ch = 0;
1715 let mut attrs = [Attr::character("parity", &mut ch)];
1716
1717 let err = read_object(r#"{"parity":"NO"}"#, &mut attrs).unwrap_err();
1718 assert_eq!(err, Error::StrLong);
1719 }
1720
1721 #[test]
1722 fn check_fields_accept_expected_value_and_reject_others() {
1723 let mut mode = 0;
1724 let mut attrs = [
1725 Attr::check("class", "TPV"),
1726 Attr::integer("mode", &mut mode).with_default(DefaultValue::Integer(-9)),
1727 ];
1728
1729 read_object(r#"{"class":"TPV","mode":3}"#, &mut attrs).unwrap();
1730 drop(attrs);
1731 assert_eq!(mode, 3);
1732
1733 let mut mode = 19;
1734 let mut attrs = [
1735 Attr::check("class", "TPV"),
1736 Attr::integer("mode", &mut mode).with_default(DefaultValue::Integer(-9)),
1737 ];
1738 let err = read_object(r#"{"class":"foo","mode":-4}"#, &mut attrs).unwrap_err();
1739 drop(attrs);
1740 assert_eq!(err, Error::CheckFail);
1741 assert_eq!(mode, -9);
1742 }
1743
1744 #[test]
1745 fn ignore_any_accepts_unknown_attributes() {
1746 let mut enable = false;
1747 let mut json = false;
1748 let mut attrs = [
1749 Attr::check("class", "WATCH"),
1750 Attr::boolean("enable", &mut enable),
1751 Attr::boolean("json", &mut json),
1752 Attr::ignore_any(),
1753 ];
1754
1755 read_object(
1756 r#"{"class":"WATCH","enable":true,"json":true,"nmea":false,"raw":0,"device":"/dev/ttyUSB0"}"#,
1757 &mut attrs,
1758 )
1759 .unwrap();
1760 drop(attrs);
1761 assert!(enable);
1762 assert!(json);
1763 }
1764
1765 #[test]
1766 fn maps_quoted_enum_values_to_integers() {
1767 const MAP: &[EnumValue<'_>] = &[
1768 EnumValue {
1769 name: "BAR",
1770 value: 6,
1771 },
1772 EnumValue {
1773 name: "FOO",
1774 value: 3,
1775 },
1776 EnumValue {
1777 name: "BAZ",
1778 value: 14,
1779 },
1780 ];
1781 let mut fee = 0;
1782 let mut fie = 0;
1783 let mut foe = 0;
1784 let mut attrs = [
1785 Attr::integer("fee", &mut fee).with_map(MAP),
1786 Attr::integer("fie", &mut fie).with_map(MAP),
1787 Attr::integer("foe", &mut foe).with_map(MAP),
1788 ];
1789
1790 read_object(r#"{"fee":"FOO","fie":"BAR","foe":"BAZ"}"#, &mut attrs).unwrap();
1791 drop(attrs);
1792 assert_eq!((fee, fie, foe), (3, 6, 14));
1793 }
1794
1795 #[test]
1796 fn rejects_unknown_enum_value() {
1797 const MAP: &[EnumValue<'_>] = &[EnumValue {
1798 name: "SET",
1799 value: 1,
1800 }];
1801 let mut value = 0;
1802 let mut attrs = [Attr::integer("state", &mut value).with_map(MAP)];
1803
1804 let err = read_object(r#"{"state":"NOPE"}"#, &mut attrs).unwrap_err();
1805 assert_eq!(err, Error::BadEnum);
1806 }
1807
1808 #[test]
1809 fn parses_integer_boolean_real_and_string_arrays() {
1810 let mut ints = [0; 4];
1811 let mut int_count = 0;
1812 let mut int_array = Array::Integers {
1813 store: &mut ints,
1814 count: Some(&mut int_count),
1815 };
1816 read_array("[23,-17,5]", &mut int_array).unwrap();
1817 drop(int_array);
1818 assert_eq!(int_count, 3);
1819 assert_eq!(ints, [23, -17, 5, 0]);
1820
1821 let mut bools = [false; 4];
1822 let mut bool_count = 0;
1823 let mut bool_array = Array::Booleans {
1824 store: &mut bools,
1825 count: Some(&mut bool_count),
1826 };
1827 read_array("[true,false,7]", &mut bool_array).unwrap();
1828 drop(bool_array);
1829 assert_eq!(bool_count, 3);
1830 assert_eq!(bools, [true, false, true, false]);
1831
1832 let mut reals = [0.0; 4];
1833 let mut real_count = 0;
1834 let mut real_array = Array::Reals {
1835 store: &mut reals,
1836 count: Some(&mut real_count),
1837 };
1838 read_array("[23.1,-17.2,5.3e1]", &mut real_array).unwrap();
1839 drop(real_array);
1840 assert_eq!(real_count, 3);
1841 assert_eq!(reals[0], 23.1);
1842 assert_eq!(reals[1], -17.2);
1843 assert_eq!(reals[2], 53.0);
1844
1845 let mut s0 = [0; 8];
1846 let mut s1 = [0; 8];
1847 let mut s2 = [0; 8];
1848 let mut string_count = 0;
1849 {
1850 let mut strings: [&mut [u8]; 3] = [&mut s0, &mut s1, &mut s2];
1851 let mut string_array = Array::Strings {
1852 store: &mut strings,
1853 count: Some(&mut string_count),
1854 };
1855 read_array(r#"["foo","b\nr","\u0042az"]"#, &mut string_array).unwrap();
1856 }
1857 assert_eq!(string_count, 3);
1858 assert_eq!(cstr(&s0), "foo");
1859 assert_eq!(cstr(&s1), "b\nr");
1860 assert_eq!(cstr(&s2), "Baz");
1861 }
1862
1863 #[test]
1864 fn parses_unsigned_and_short_arrays() {
1865 let mut uints = [0; 3];
1866 let mut shorts = [0; 3];
1867 let mut ushorts = [0; 3];
1868
1869 let mut arr = Array::UIntegers {
1870 store: &mut uints,
1871 count: None,
1872 };
1873 read_array("[1,2,4294967295]", &mut arr).unwrap();
1874 drop(arr);
1875 assert_eq!(uints, [1, 2, u32::MAX]);
1876
1877 let mut arr = Array::Shorts {
1878 store: &mut shorts,
1879 count: None,
1880 };
1881 read_array("[-32768,0,32767]", &mut arr).unwrap();
1882 drop(arr);
1883 assert_eq!(shorts, [i16::MIN, 0, i16::MAX]);
1884
1885 let mut arr = Array::UShorts {
1886 store: &mut ushorts,
1887 count: None,
1888 };
1889 read_array("[0,65535,17]", &mut arr).unwrap();
1890 drop(arr);
1891 assert_eq!(ushorts, [0, u16::MAX, 17]);
1892 }
1893
1894 #[test]
1895 fn parses_nested_objects() {
1896 let mut name = [0; 16];
1897 let mut inner = 0;
1898 let mut innerinner = 0;
1899 let mut inner2_attrs = [Attr::integer("innerinner", &mut innerinner)];
1900 let mut inner1_attrs = [
1901 Attr::integer("inner", &mut inner),
1902 Attr::object("innerobject", &mut inner2_attrs),
1903 ];
1904 let mut attrs = [
1905 Attr::string("name", &mut name),
1906 Attr::object("value", &mut inner1_attrs),
1907 ];
1908
1909 read_object(
1910 r#"{"name":"wobble","value":{"inner":23,"innerobject":{"innerinner":123}}}"#,
1911 &mut attrs,
1912 )
1913 .unwrap();
1914 drop(attrs);
1915 assert_eq!(cstr(&name), "wobble");
1916 assert_eq!(inner, 23);
1917 assert_eq!(innerinner, 123);
1918 }
1919
1920 #[derive(Clone, Copy)]
1921 struct DevConfig {
1922 path: [u8; 32],
1923 activated: f64,
1924 }
1925
1926 impl DevConfig {
1927 const fn new() -> Self {
1928 Self {
1929 path: [0; 32],
1930 activated: 0.0,
1931 }
1932 }
1933 }
1934
1935 #[test]
1936 fn parses_structobject_array_with_callback() {
1937 let mut devices = [DevConfig::new(); 4];
1938 let mut count = 0;
1939 let mut parse_device = |s: &str, index: usize| {
1940 let dev = &mut devices[index];
1941 let mut attrs = [
1942 Attr::string("path", &mut dev.path),
1943 Attr::real("activated", &mut dev.activated),
1944 ];
1945 read_object(s, &mut attrs)
1946 };
1947 let mut attrs = [Attr::array(
1948 "devices",
1949 Array::StructObjects {
1950 maxlen: 4,
1951 count: Some(&mut count),
1952 parser: &mut parse_device,
1953 },
1954 )];
1955
1956 read_object(
1957 r#"{"devices":[{"path":"/dev/ttyUSB0","activated":1411468340},{"path":"/dev/ttyUSB1","activated":2.5}]}"#,
1958 &mut attrs,
1959 )
1960 .unwrap();
1961 drop(attrs);
1962 assert_eq!(count, 2);
1963 assert_eq!(cstr(&devices[0].path), "/dev/ttyUSB0");
1964 assert_eq!(devices[0].activated, 1411468340.0);
1965 assert_eq!(cstr(&devices[1].path), "/dev/ttyUSB1");
1966 assert_eq!(devices[1].activated, 2.5);
1967 }
1968
1969 #[test]
1970 fn empty_arrays_set_count_to_zero() {
1971 let mut ints = [42; 2];
1972 let mut count = 99;
1973 let mut arr = Array::Integers {
1974 store: &mut ints,
1975 count: Some(&mut count),
1976 };
1977
1978 read_array("[]", &mut arr).unwrap();
1979 drop(arr);
1980 assert_eq!(count, 0);
1981 assert_eq!(ints, [42, 42]);
1982 }
1983
1984 #[test]
1985 fn returned_end_skips_trailing_whitespace() {
1986 let mut flag = false;
1987 let input = " {\"flag\":true} next";
1988 let mut attrs = [Attr::boolean("flag", &mut flag)];
1989
1990 let end = read_object(input, &mut attrs).unwrap();
1991 drop(attrs);
1992 assert_eq!(&input[end..], "next");
1993 assert!(flag);
1994 }
1995
1996 #[test]
1997 fn rejects_array_overflow() {
1998 let mut ints = [0; 2];
1999 let mut arr = Array::Integers {
2000 store: &mut ints,
2001 count: None,
2002 };
2003
2004 let err = read_array("[1,2,3]", &mut arr).unwrap_err();
2005 assert_eq!(err, Error::SubTooLong);
2006 }
2007
2008 #[test]
2009 fn rejects_unknown_attribute_without_ignore() {
2010 let mut known = 0;
2011 let mut attrs = [Attr::integer("known", &mut known)];
2012
2013 let err = read_object(r#"{"unknown":1}"#, &mut attrs).unwrap_err();
2014 assert_eq!(err, Error::BadAttr);
2015 }
2016
2017 #[test]
2018 fn rejects_mismatched_quotedness() {
2019 let mut int_value = 0;
2020 let mut attrs = [Attr::integer("count", &mut int_value)];
2021 let err = read_object(r#"{"count":"1"}"#, &mut attrs).unwrap_err();
2022 assert_eq!(err, Error::QNonString);
2023
2024 let mut text = [0; 8];
2025 let mut attrs = [Attr::string("name", &mut text)];
2026 let err = read_object(r#"{"name":1}"#, &mut attrs).unwrap_err();
2027 assert_eq!(err, Error::NonQString);
2028 }
2029
2030 #[test]
2031 fn rejects_bad_numbers_and_range_overflow() {
2032 let mut int_value = 0;
2033 let mut attrs = [Attr::integer("count", &mut int_value)];
2034 let err = read_object(r#"{"count":2147483648}"#, &mut attrs).unwrap_err();
2035 assert_eq!(err, Error::BadNum);
2036
2037 let mut uint_value = 0;
2038 let mut attrs = [Attr::uinteger("count", &mut uint_value)];
2039 let err = read_object(r#"{"count":-1}"#, &mut attrs).unwrap_err();
2040 assert_eq!(err, Error::BadNum);
2041
2042 let mut real_value = 0.0;
2043 let mut attrs = [Attr::real("value", &mut real_value)];
2044 let err = read_object(r#"{"value":1e}"#, &mut attrs).unwrap_err();
2045 assert_eq!(err, Error::BadNum);
2046 }
2047
2048 #[test]
2049 fn rejects_bad_object_and_array_syntax() {
2050 let mut value = 0;
2051 let mut attrs = [Attr::integer("value", &mut value)];
2052 assert_eq!(read_object("", &mut attrs).unwrap_err(), Error::Empty);
2053 assert_eq!(read_object("[]", &mut attrs).unwrap_err(), Error::ObStart);
2054 assert_eq!(
2055 read_object("{value:1}", &mut attrs).unwrap_err(),
2056 Error::AttrStart
2057 );
2058 assert_eq!(
2059 read_object(r#"{"value":1 junk}"#, &mut attrs).unwrap_err(),
2060 Error::BadTrail
2061 );
2062
2063 let mut arr = Array::Integers {
2064 store: &mut [0; 2],
2065 count: None,
2066 };
2067 assert_eq!(read_array("{}", &mut arr).unwrap_err(), Error::ArrayStart);
2068 assert_eq!(
2069 read_array("[1 2]", &mut arr).unwrap_err(),
2070 Error::BadSubTrail
2071 );
2072 }
2073
2074 #[test]
2075 fn rejects_expected_array_or_object_when_missing() {
2076 let mut ints = [0; 2];
2077 let mut attrs = [Attr::array(
2078 "arr",
2079 Array::Integers {
2080 store: &mut ints,
2081 count: None,
2082 },
2083 )];
2084 assert_eq!(
2085 read_object(r#"{"arr":1}"#, &mut attrs).unwrap_err(),
2086 Error::NoBrak
2087 );
2088
2089 let mut value = 0;
2090 let mut child = [Attr::integer("value", &mut value)];
2091 let mut attrs = [Attr::object("child", &mut child)];
2092 assert_eq!(
2093 read_object(r#"{"child":1}"#, &mut attrs).unwrap_err(),
2094 Error::NoCurly
2095 );
2096 }
2097
2098 #[test]
2099 fn rejects_unexpected_array_or_object_values() {
2100 let mut value = 0;
2101 let mut attrs = [Attr::integer("value", &mut value)];
2102 assert_eq!(
2103 read_object(r#"{"value":[1]}"#, &mut attrs).unwrap_err(),
2104 Error::NoArray
2105 );
2106 assert_eq!(
2107 read_object(r#"{"value":{"x":1}}"#, &mut attrs).unwrap_err(),
2108 Error::NoArray
2109 );
2110 }
2111
2112 #[test]
2113 fn rejects_too_long_attribute_name() {
2114 let mut value = 0;
2115 let mut attrs = [Attr::integer("value", &mut value)];
2116 let err = read_object(r#"{"abcdefghijklmnopqrstuvwxyzabcdef":1}"#, &mut attrs).unwrap_err();
2117 assert_eq!(err, Error::AttrLen);
2118 }
2119
2120 #[test]
2121 fn rejects_invalid_string_escape() {
2122 let mut text = [0; 8];
2123 let mut attrs = [Attr::string("text", &mut text)];
2124
2125 let err = read_object(r#"{"text":"\u12x4"}"#, &mut attrs).unwrap_err();
2126 assert_eq!(err, Error::BadString);
2127 }
2128
2129 #[test]
2130 fn rejects_parallel_object_arrays_with_string_fields_after_first_element() {
2131 let mut names = [0; 16];
2132 let mut subattrs = [Attr::string("name", &mut names)];
2133 let mut attrs = [Attr::array(
2134 "items",
2135 Array::Objects {
2136 attrs: &mut subattrs,
2137 maxlen: 2,
2138 count: None,
2139 },
2140 )];
2141
2142 let err =
2143 read_object(r#"{"items":[{"name":"one"},{"name":"two"}]}"#, &mut attrs).unwrap_err();
2144 assert_eq!(err, Error::NoParStr);
2145 }
2146}