Skip to main content

fixed_json/
parser.rs

1use crate::{
2    Array, Attr, AttrKind, DefaultValue, Error, JSON_ATTR_MAX, JSON_VAL_MAX, Result,
3    number::{
4        hex_val, json_number_is_integer, json_number_is_real, parse_bool_at, parse_f64_at,
5        parse_f64_token, parse_i16_at, parse_i16_token, parse_i32_at, parse_i32_token,
6        parse_i64_token, parse_u16_at, parse_u16_token, parse_u32_at, parse_u32_token,
7        write_i32_token,
8    },
9};
10
11#[inline]
12pub fn read_object(input: &str, attrs: &mut [Attr<'_>]) -> Result<usize> {
13    read_object_internal(input, attrs, None, 0)
14}
15
16#[inline]
17pub fn read_array(input: &str, array: &mut Array<'_>) -> Result<usize> {
18    read_array_internal(input, array)
19}
20
21#[inline]
22pub fn cstr(buf: &[u8]) -> &str {
23    let len = buf.iter().position(|&b| b == 0).unwrap_or(buf.len());
24    core::str::from_utf8(&buf[..len]).unwrap_or("")
25}
26
27fn read_object_internal(
28    input: &str,
29    attrs: &mut [Attr<'_>],
30    parent_is_structobject: Option<bool>,
31    offset: usize,
32) -> Result<usize> {
33    apply_defaults(attrs, parent_is_structobject, offset)?;
34
35    let bytes = input.as_bytes();
36    let mut i = skip_ws(bytes, 0);
37    if i >= bytes.len() {
38        return Err(Error::Empty);
39    }
40    if bytes[i] != b'{' {
41        return Err(Error::ObStart);
42    }
43    i += 1;
44
45    loop {
46        i = skip_ws(bytes, i);
47        if i >= bytes.len() {
48            return Err(Error::AttrStart);
49        }
50        if bytes[i] == b'}' {
51            i += 1;
52            return Ok(skip_ws(bytes, i));
53        }
54        if bytes[i] != b'"' {
55            return Err(Error::AttrStart);
56        }
57        i += 1;
58
59        let mut attr_buf = [0u8; JSON_ATTR_MAX + 1];
60        let attr_len = parse_attr_name(bytes, &mut i, &mut attr_buf)?;
61        let attr_name = core::str::from_utf8(&attr_buf[..attr_len]).map_err(|_| Error::BadAttr)?;
62        let first = find_attr(attrs, attr_name).ok_or(Error::BadAttr)?;
63
64        i = skip_ws(bytes, i);
65        if i >= bytes.len() || bytes[i] != b':' {
66            return Err(Error::BadTrail);
67        }
68        i += 1;
69        i = skip_ws(bytes, i);
70        if i >= bytes.len() {
71            return Err(Error::BadTrail);
72        }
73
74        if bytes[i] == b'[' {
75            if !matches!(attrs[first].kind, AttrKind::Array(_)) {
76                return Err(Error::NoArray);
77            }
78            let AttrKind::Array(array) = &mut attrs[first].kind else {
79                unreachable!();
80            };
81            i += read_array_internal(&input[i..], array)?;
82            i = skip_ws(bytes, i);
83        } else if matches!(attrs[first].kind, AttrKind::Array(_)) {
84            return Err(Error::NoBrak);
85        } else if bytes[i] == b'{' {
86            if !matches!(attrs[first].kind, AttrKind::Object(_)) {
87                return Err(Error::NoArray);
88            }
89            let AttrKind::Object(child) = &mut attrs[first].kind else {
90                unreachable!();
91            };
92            i += read_object_internal(&input[i..], child, None, 0)?;
93            i = skip_ws(bytes, i);
94        } else if matches!(attrs[first].kind, AttrKind::Object(_)) {
95            return Err(Error::NoCurly);
96        } else {
97            let mut val_buf = [0u8; JSON_VAL_MAX + 1];
98            let quoted = if bytes[i] == b'"' {
99                i += 1;
100                let maxlen = value_max_len(&attrs[first]);
101                parse_string_value(bytes, &mut i, &mut val_buf, maxlen)?;
102                true
103            } else {
104                parse_token_value(bytes, &mut i, &mut val_buf)?;
105                false
106            };
107            let selected = select_attr(attrs, first, attr_name, &val_buf, quoted)?;
108            apply_value(
109                &mut attrs[selected],
110                parent_is_structobject,
111                offset,
112                &val_buf,
113                quoted,
114            )?;
115            i = skip_ws(bytes, i);
116        }
117
118        if i >= bytes.len() {
119            return Err(Error::BadTrail);
120        }
121        if bytes[i] == b',' {
122            i += 1;
123        } else if bytes[i] == b'}' {
124            i += 1;
125            return Ok(skip_ws(bytes, i));
126        } else {
127            return Err(Error::BadTrail);
128        }
129    }
130}
131
132fn read_array_internal(input: &str, array: &mut Array<'_>) -> Result<usize> {
133    let bytes = input.as_bytes();
134    let mut i = skip_ws(bytes, 0);
135    if i >= bytes.len() || bytes[i] != b'[' {
136        return Err(Error::ArrayStart);
137    }
138    i += 1;
139    i = skip_ws(bytes, i);
140    if i < bytes.len() && bytes[i] == b']' {
141        set_array_count(array, 0);
142        return Ok(skip_ws(bytes, i + 1));
143    }
144
145    let maxlen = array_maxlen(array);
146    let mut count = 0usize;
147    while count < maxlen {
148        i = skip_ws(bytes, i);
149        match array {
150            Array::Strings { store, .. } => {
151                if i >= bytes.len() || bytes[i] != b'"' {
152                    return Err(Error::BadString);
153                }
154                i += 1;
155                parse_string_value(
156                    bytes,
157                    &mut i,
158                    store[count],
159                    store[count].len().saturating_sub(1),
160                )?;
161            }
162            Array::Integers { store, .. } => {
163                let (v, end) = parse_i32_at(bytes, i)?;
164                store[count] = v;
165                i = end;
166            }
167            Array::UIntegers { store, .. } => {
168                let (v, end) = parse_u32_at(bytes, i)?;
169                store[count] = v;
170                i = end;
171            }
172            Array::Shorts { store, .. } => {
173                let (v, end) = parse_i16_at(bytes, i)?;
174                store[count] = v;
175                i = end;
176            }
177            Array::UShorts { store, .. } => {
178                let (v, end) = parse_u16_at(bytes, i)?;
179                store[count] = v;
180                i = end;
181            }
182            Array::Reals { store, .. } => {
183                let (v, end) = parse_f64_at(bytes, i)?;
184                store[count] = v;
185                i = end;
186            }
187            Array::Booleans { store, .. } => {
188                let (v, end) = parse_bool_at(bytes, i)?;
189                store[count] = v;
190                i = end;
191            }
192            Array::Objects { attrs, .. } => {
193                i += read_object_internal(&input[i..], attrs, Some(false), count)?;
194            }
195            Array::StructObjects { parser, .. } => {
196                i += parser(&input[i..], count)?;
197            }
198        }
199        count += 1;
200        i = skip_ws(bytes, i);
201        if i < bytes.len() && bytes[i] == b']' {
202            set_array_count(array, count);
203            return Ok(skip_ws(bytes, i + 1));
204        }
205        if i < bytes.len() && bytes[i] == b',' {
206            i += 1;
207        } else {
208            return Err(Error::BadSubTrail);
209        }
210    }
211
212    Err(Error::SubTooLong)
213}
214
215fn apply_defaults(
216    attrs: &mut [Attr<'_>],
217    parent_is_structobject: Option<bool>,
218    offset: usize,
219) -> Result<()> {
220    for attr in attrs {
221        if attr.nodefault {
222            continue;
223        }
224        match attr.default {
225            DefaultValue::None => {
226                if let AttrKind::String(buf) = &mut attr.kind {
227                    if matches!(parent_is_structobject, Some(false)) && offset > 0 {
228                        return Err(Error::NoParStr);
229                    }
230                    clear_cbuf(buf);
231                }
232            }
233            DefaultValue::Integer(v) => set_i32(&mut attr.kind, offset, v)?,
234            DefaultValue::UInteger(v) => set_u32(&mut attr.kind, offset, v)?,
235            DefaultValue::Short(v) => set_i16(&mut attr.kind, offset, v)?,
236            DefaultValue::UShort(v) => set_u16(&mut attr.kind, offset, v)?,
237            DefaultValue::Real(v) => set_f64(&mut attr.kind, offset, v)?,
238            DefaultValue::Boolean(v) => set_bool(&mut attr.kind, offset, v)?,
239            DefaultValue::Character(v) => set_char(&mut attr.kind, offset, v)?,
240            DefaultValue::Check(_) => {}
241        }
242    }
243    Ok(())
244}
245
246fn parse_attr_name(
247    bytes: &[u8],
248    i: &mut usize,
249    out: &mut [u8; JSON_ATTR_MAX + 1],
250) -> Result<usize> {
251    let mut len = 0usize;
252    while *i < bytes.len() {
253        let b = bytes[*i];
254        *i += 1;
255        if b == b'"' {
256            return Ok(len);
257        }
258        if len >= JSON_ATTR_MAX {
259            return Err(Error::AttrLen);
260        }
261        out[len] = b;
262        len += 1;
263    }
264    Err(Error::BadString)
265}
266
267fn parse_string_value(
268    bytes: &[u8],
269    i: &mut usize,
270    out: &mut [u8],
271    max_content_len: usize,
272) -> Result<usize> {
273    clear_cbuf(out);
274    let mut len = 0usize;
275    while *i < bytes.len() {
276        let b = bytes[*i];
277        *i += 1;
278        let outb = if b == b'\\' {
279            if *i >= bytes.len() {
280                return Err(Error::BadString);
281            }
282            let e = bytes[*i];
283            *i += 1;
284            match e {
285                b'b' => 8,
286                b'f' => 12,
287                b'n' => b'\n',
288                b'r' => b'\r',
289                b't' => b'\t',
290                b'u' => {
291                    if *i + 4 > bytes.len() {
292                        return Err(Error::BadString);
293                    }
294                    let mut v = 0u32;
295                    for _ in 0..4 {
296                        let Some(d) = hex_val(bytes[*i]) else {
297                            return Err(Error::BadString);
298                        };
299                        v = (v << 4) | d as u32;
300                        *i += 1;
301                    }
302                    v as u8
303                }
304                other => other,
305            }
306        } else if b == b'"' {
307            if len < out.len() {
308                out[len] = 0;
309            }
310            return Ok(len);
311        } else {
312            b
313        };
314        if len >= JSON_VAL_MAX || len >= max_content_len || len + 1 > out.len() {
315            return Err(Error::StrLong);
316        }
317        out[len] = outb;
318        len += 1;
319    }
320    Err(Error::BadString)
321}
322
323fn parse_token_value(
324    bytes: &[u8],
325    i: &mut usize,
326    out: &mut [u8; JSON_VAL_MAX + 1],
327) -> Result<usize> {
328    let mut len = 0usize;
329    while *i < bytes.len() {
330        let b = bytes[*i];
331        if is_ws(b) || b == b',' || b == b'}' || b == b']' {
332            out[len] = 0;
333            return Ok(len);
334        }
335        if len >= JSON_VAL_MAX {
336            return Err(Error::TokLong);
337        }
338        out[len] = b;
339        len += 1;
340        *i += 1;
341    }
342    out[len] = 0;
343    Ok(len)
344}
345
346fn find_attr(attrs: &[Attr<'_>], name: &str) -> Option<usize> {
347    let mut ignore = None;
348    for (idx, attr) in attrs.iter().enumerate() {
349        if attr.name == name {
350            return Some(idx);
351        }
352        if attr.name.is_empty() && matches!(attr.kind, AttrKind::Ignore) {
353            ignore = Some(idx);
354        }
355    }
356    ignore
357}
358
359fn select_attr(
360    attrs: &[Attr<'_>],
361    first: usize,
362    name: &str,
363    val: &[u8; JSON_VAL_MAX + 1],
364    quoted: bool,
365) -> Result<usize> {
366    let mut idx = first;
367    loop {
368        if value_fits_attr(&attrs[idx], val, quoted) {
369            break;
370        }
371        if idx + 1 >= attrs.len() || attrs[idx + 1].name != name {
372            break;
373        }
374        idx += 1;
375    }
376
377    let attr = &attrs[idx];
378    if quoted
379        && !matches!(
380            attr.kind,
381            AttrKind::String(_)
382                | AttrKind::Character(_)
383                | AttrKind::Check(_)
384                | AttrKind::Time(_)
385                | AttrKind::Ignore
386        )
387        && attr.map.is_none()
388    {
389        return Err(Error::QNonString);
390    }
391    if !quoted
392        && (matches!(
393            attr.kind,
394            AttrKind::String(_) | AttrKind::Check(_) | AttrKind::Time(_)
395        ) || attr.map.is_some())
396    {
397        return Err(Error::NonQString);
398    }
399    Ok(idx)
400}
401
402fn value_fits_attr(attr: &Attr<'_>, val: &[u8; JSON_VAL_MAX + 1], quoted: bool) -> bool {
403    if quoted {
404        return matches!(attr.kind, AttrKind::String(_) | AttrKind::Time(_));
405    }
406    if token_eq(val, b"true") || token_eq(val, b"false") {
407        return matches!(attr.kind, AttrKind::Boolean(_));
408    }
409    if json_number_is_integer(val) {
410        return matches!(
411            attr.kind,
412            AttrKind::Integer(_) | AttrKind::UInteger(_) | AttrKind::Short(_) | AttrKind::UShort(_)
413        );
414    }
415    if json_number_is_real(val) {
416        return matches!(attr.kind, AttrKind::Real(_));
417    }
418    false
419}
420
421fn apply_value(
422    attr: &mut Attr<'_>,
423    parent_is_structobject: Option<bool>,
424    offset: usize,
425    val: &[u8; JSON_VAL_MAX + 1],
426    _quoted: bool,
427) -> Result<()> {
428    let mut mapped_buf = [0u8; JSON_VAL_MAX + 1];
429    let val = if let Some(map) = attr.map {
430        let s = token_str(val)?;
431        let mut found = None;
432        for item in map {
433            if item.name == s {
434                found = Some(item.value);
435                break;
436            }
437        }
438        let Some(found) = found else {
439            return Err(Error::BadEnum);
440        };
441        write_i32_token(found, &mut mapped_buf);
442        &mapped_buf
443    } else {
444        val
445    };
446
447    match &mut attr.kind {
448        AttrKind::Integer(_) => {
449            let v = parse_i32_token(val)?;
450            set_i32(&mut attr.kind, offset, v)
451        }
452        AttrKind::UInteger(_) => {
453            let v = parse_u32_token(val)?;
454            set_u32(&mut attr.kind, offset, v)
455        }
456        AttrKind::Short(_) => {
457            let v = parse_i16_token(val)?;
458            set_i16(&mut attr.kind, offset, v)
459        }
460        AttrKind::UShort(_) => {
461            let v = parse_u16_token(val)?;
462            set_u16(&mut attr.kind, offset, v)
463        }
464        AttrKind::Real(_) => {
465            let v = parse_f64_token(val)?;
466            set_f64(&mut attr.kind, offset, v)
467        }
468        AttrKind::String(buf) => {
469            if matches!(parent_is_structobject, Some(false)) && offset > 0 {
470                return Err(Error::NoParStr);
471            }
472            copy_cbuf(buf, val);
473            Ok(())
474        }
475        AttrKind::Boolean(_) => {
476            let v = if token_eq(val, b"true") {
477                true
478            } else if token_eq(val, b"false") {
479                false
480            } else {
481                parse_i64_token(val)? != 0
482            };
483            set_bool(&mut attr.kind, offset, v)
484        }
485        AttrKind::Character(_) => {
486            let len = token_len(val);
487            if len > 1 {
488                return Err(Error::StrLong);
489            }
490            set_char(&mut attr.kind, offset, if len == 0 { 0 } else { val[0] })
491        }
492        AttrKind::Check(expected) => {
493            if token_str(val)? == *expected {
494                Ok(())
495            } else {
496                Err(Error::CheckFail)
497            }
498        }
499        AttrKind::Ignore => Ok(()),
500        AttrKind::Time(_) => Ok(()),
501        AttrKind::Object(_) | AttrKind::Array(_) => Ok(()),
502    }
503}
504
505#[inline]
506fn set_i32(kind: &mut AttrKind<'_>, offset: usize, value: i32) -> Result<()> {
507    if let AttrKind::Integer(target) = kind {
508        target.set(offset, value)?;
509    }
510    Ok(())
511}
512
513#[inline]
514fn set_u32(kind: &mut AttrKind<'_>, offset: usize, value: u32) -> Result<()> {
515    if let AttrKind::UInteger(target) = kind {
516        target.set(offset, value)?;
517    }
518    Ok(())
519}
520
521#[inline]
522fn set_i16(kind: &mut AttrKind<'_>, offset: usize, value: i16) -> Result<()> {
523    if let AttrKind::Short(target) = kind {
524        target.set(offset, value)?;
525    }
526    Ok(())
527}
528
529#[inline]
530fn set_u16(kind: &mut AttrKind<'_>, offset: usize, value: u16) -> Result<()> {
531    if let AttrKind::UShort(target) = kind {
532        target.set(offset, value)?;
533    }
534    Ok(())
535}
536
537#[inline]
538fn set_f64(kind: &mut AttrKind<'_>, offset: usize, value: f64) -> Result<()> {
539    match kind {
540        AttrKind::Real(target) | AttrKind::Time(target) => target.set(offset, value)?,
541        _ => {}
542    }
543    Ok(())
544}
545
546#[inline]
547fn set_bool(kind: &mut AttrKind<'_>, offset: usize, value: bool) -> Result<()> {
548    if let AttrKind::Boolean(target) = kind {
549        target.set(offset, value)?;
550    }
551    Ok(())
552}
553
554#[inline]
555fn set_char(kind: &mut AttrKind<'_>, offset: usize, value: u8) -> Result<()> {
556    if let AttrKind::Character(target) = kind {
557        target.set(offset, value)?;
558    }
559    Ok(())
560}
561
562#[inline]
563fn value_max_len(attr: &Attr<'_>) -> usize {
564    match &attr.kind {
565        AttrKind::String(buf) => buf.len().saturating_sub(1),
566        AttrKind::Check(expected) => expected.len(),
567        _ => JSON_VAL_MAX,
568    }
569}
570
571#[inline]
572fn array_maxlen(array: &Array<'_>) -> usize {
573    match array {
574        Array::Strings { store, .. } => store.len(),
575        Array::Integers { store, .. } => store.len(),
576        Array::UIntegers { store, .. } => store.len(),
577        Array::Shorts { store, .. } => store.len(),
578        Array::UShorts { store, .. } => store.len(),
579        Array::Reals { store, .. } => store.len(),
580        Array::Booleans { store, .. } => store.len(),
581        Array::Objects { maxlen, .. } => *maxlen,
582        Array::StructObjects { maxlen, .. } => *maxlen,
583    }
584}
585
586#[inline]
587fn set_array_count(array: &mut Array<'_>, value: usize) {
588    match array {
589        Array::Strings { count, .. }
590        | Array::Integers { count, .. }
591        | Array::UIntegers { count, .. }
592        | Array::Shorts { count, .. }
593        | Array::UShorts { count, .. }
594        | Array::Reals { count, .. }
595        | Array::Booleans { count, .. }
596        | Array::Objects { count, .. }
597        | Array::StructObjects { count, .. } => {
598            if let Some(count) = count {
599                **count = value;
600            }
601        }
602    }
603}
604
605#[inline]
606fn skip_ws(bytes: &[u8], mut i: usize) -> usize {
607    while i < bytes.len() && is_ws(bytes[i]) {
608        i += 1;
609    }
610    i
611}
612
613#[inline]
614fn is_ws(b: u8) -> bool {
615    matches!(b, b' ' | b'\t' | b'\n' | b'\r' | 0x0c | 0x0b)
616}
617
618#[inline]
619fn clear_cbuf(buf: &mut [u8]) {
620    for b in buf {
621        *b = 0;
622    }
623}
624
625#[inline]
626fn copy_cbuf(out: &mut [u8], val: &[u8; JSON_VAL_MAX + 1]) {
627    clear_cbuf(out);
628    if out.is_empty() {
629        return;
630    }
631    let n = core::cmp::min(token_len(val), out.len() - 1);
632    out[..n].copy_from_slice(&val[..n]);
633}
634
635#[inline]
636fn token_len(token: &[u8]) -> usize {
637    token.iter().position(|&b| b == 0).unwrap_or(token.len())
638}
639
640#[inline]
641fn token_str(token: &[u8]) -> Result<&str> {
642    core::str::from_utf8(&token[..token_len(token)]).map_err(|_| Error::BadString)
643}
644
645#[inline]
646fn token_eq(token: &[u8], expected: &[u8]) -> bool {
647    &token[..token_len(token)] == expected
648}