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}