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