Skip to main content

fixed_json/
lib.rs

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