Skip to main content

fixed_json/
parser.rs

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}