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