1use std::borrow::Cow;
2use std::fmt;
3use std::io::{Read, Write};
4use std::ops::Index;
5
6
7#[derive(Clone, Debug, PartialEq)]
8pub enum JsonNumber {
9 I64(i64),
10 U64(u64),
11 F64(f64),
12}
13
14#[derive(Clone, Debug, PartialEq)]
15pub enum JsonValue {
16 Null,
17 Bool(bool),
18 Number(JsonNumber),
19 String(String),
20 Array(Vec<JsonValue>),
21 Object(Vec<(String, JsonValue)>),
22}
23
24pub type Value = JsonValue;
25pub type Number = JsonNumber;
26pub type Map = Vec<(String, JsonValue)>;
27
28#[derive(Clone, Debug, PartialEq)]
29pub enum BorrowedJsonValue<'a> {
30 Null,
31 Bool(bool),
32 Number(JsonNumber),
33 String(Cow<'a, str>),
34 Array(Vec<BorrowedJsonValue<'a>>),
35 Object(Vec<(Cow<'a, str>, BorrowedJsonValue<'a>)>),
36}
37
38#[derive(Clone, Debug, PartialEq, Eq)]
39pub struct CompiledObjectSchema {
40 fields: Vec<CompiledField>,
41 capacity_hint: usize,
42}
43
44#[derive(Clone, Debug, PartialEq, Eq)]
45pub struct CompiledRowSchema {
46 object: CompiledObjectSchema,
47 row_capacity_hint: usize,
48}
49
50#[derive(Clone, Debug, PartialEq, Eq)]
51pub struct JsonTape {
52 pub tokens: Vec<TapeToken>,
53}
54
55#[derive(Clone, Debug, PartialEq, Eq)]
56pub struct TapeToken {
57 pub kind: TapeTokenKind,
58 pub start: usize,
59 pub end: usize,
60 pub parent: Option<usize>,
61}
62
63#[derive(Clone, Copy, Debug, PartialEq, Eq)]
64pub enum TapeTokenKind {
65 Null,
66 Bool,
67 Number,
68 String,
69 Key,
70 Array,
71 Object,
72}
73
74#[derive(Clone, Copy, Debug, PartialEq, Eq)]
75pub struct TapeValue<'a> {
76 tape: &'a JsonTape,
77 input: &'a str,
78 index: usize,
79}
80
81#[derive(Clone, Debug, PartialEq, Eq)]
82pub struct TapeObjectIndex {
83 buckets: Vec<Vec<(u64, usize, usize)>>,
84}
85
86#[derive(Clone, Copy, Debug)]
87pub struct IndexedTapeObject<'a> {
88 object: TapeValue<'a>,
89 index: &'a TapeObjectIndex,
90}
91
92#[derive(Clone, Debug, PartialEq, Eq)]
93pub struct CompiledTapeKey {
94 key: String,
95 hash: u64,
96}
97
98#[derive(Clone, Debug, PartialEq, Eq)]
99pub struct CompiledTapeKeys {
100 keys: Vec<CompiledTapeKey>,
101}
102
103#[derive(Clone, Debug, PartialEq, Eq)]
104struct CompiledField {
105 key: String,
106 rendered_prefix: Vec<u8>,
107}
108
109#[derive(Clone, Debug, PartialEq, Eq)]
110pub enum JsonError {
111 NonFiniteNumber,
112 Io,
113}
114
115#[derive(Clone, Debug, PartialEq, Eq)]
116pub enum JsonParseError {
117 InvalidUtf8,
118 UnexpectedEnd,
119 UnexpectedTrailingCharacters(usize),
120 UnexpectedCharacter { index: usize, found: char },
121 InvalidLiteral { index: usize },
122 InvalidNumber { index: usize },
123 InvalidEscape { index: usize },
124 InvalidUnicodeEscape { index: usize },
125 InvalidUnicodeScalar { index: usize },
126 ExpectedColon { index: usize },
127 ExpectedCommaOrEnd { index: usize, context: &'static str },
128}
129
130impl fmt::Display for JsonError {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 match self {
133 Self::NonFiniteNumber => {
134 f.write_str("cannot serialize non-finite floating-point value")
135 }
136 Self::Io => f.write_str("i/o error while serializing JSON"),
137 }
138 }
139}
140
141impl fmt::Display for JsonParseError {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 match self {
144 Self::InvalidUtf8 => f.write_str("input is not valid UTF-8"),
145 Self::UnexpectedEnd => f.write_str("unexpected end of JSON input"),
146 Self::UnexpectedTrailingCharacters(index) => {
147 write!(f, "unexpected trailing characters at byte {index}")
148 }
149 Self::UnexpectedCharacter { index, found } => {
150 write!(f, "unexpected character '{found}' at byte {index}")
151 }
152 Self::InvalidLiteral { index } => write!(f, "invalid literal at byte {index}"),
153 Self::InvalidNumber { index } => write!(f, "invalid number at byte {index}"),
154 Self::InvalidEscape { index } => write!(f, "invalid escape sequence at byte {index}"),
155 Self::InvalidUnicodeEscape { index } => {
156 write!(f, "invalid unicode escape at byte {index}")
157 }
158 Self::InvalidUnicodeScalar { index } => {
159 write!(f, "invalid unicode scalar at byte {index}")
160 }
161 Self::ExpectedColon { index } => write!(f, "expected ':' at byte {index}"),
162 Self::ExpectedCommaOrEnd { index, context } => {
163 write!(f, "expected ',' or end of {context} at byte {index}")
164 }
165 }
166 }
167}
168
169impl std::error::Error for JsonError {}
170impl std::error::Error for JsonParseError {}
171
172impl JsonValue {
173 pub fn object(entries: Vec<(impl Into<String>, JsonValue)>) -> Self {
174 Self::Object(
175 entries
176 .into_iter()
177 .map(|(key, value)| (key.into(), value))
178 .collect(),
179 )
180 }
181
182 pub fn array(values: Vec<JsonValue>) -> Self {
183 Self::Array(values)
184 }
185
186 pub fn to_json_string(&self) -> Result<String, JsonError> {
187 let mut out = Vec::with_capacity(initial_json_capacity(self));
188 write_json_value(&mut out, self)?;
189 Ok(unsafe { String::from_utf8_unchecked(out) })
190 }
191
192 pub fn push_field(&mut self, key: impl Into<String>, value: impl Into<JsonValue>) {
193 match self {
194 Self::Object(entries) => entries.push((key.into(), value.into())),
195 _ => panic!("push_field called on non-object JSON value"),
196 }
197 }
198
199 pub fn push_item(&mut self, value: impl Into<JsonValue>) {
200 match self {
201 Self::Array(values) => values.push(value.into()),
202 _ => panic!("push_item called on non-array JSON value"),
203 }
204 }
205
206 pub fn is_null(&self) -> bool {
207 matches!(self, Self::Null)
208 }
209
210 pub fn is_boolean(&self) -> bool {
211 matches!(self, Self::Bool(_))
212 }
213
214 pub fn is_number(&self) -> bool {
215 matches!(self, Self::Number(_))
216 }
217
218 pub fn is_string(&self) -> bool {
219 matches!(self, Self::String(_))
220 }
221
222 pub fn is_array(&self) -> bool {
223 matches!(self, Self::Array(_))
224 }
225
226 pub fn is_object(&self) -> bool {
227 matches!(self, Self::Object(_))
228 }
229
230 pub fn as_bool(&self) -> Option<bool> {
231 match self {
232 Self::Bool(value) => Some(*value),
233 _ => None,
234 }
235 }
236
237 pub fn as_i64(&self) -> Option<i64> {
238 match self {
239 Self::Number(JsonNumber::I64(value)) => Some(*value),
240 Self::Number(JsonNumber::U64(value)) => (*value <= i64::MAX as u64).then_some(*value as i64),
241 _ => None,
242 }
243 }
244
245 pub fn as_u64(&self) -> Option<u64> {
246 match self {
247 Self::Number(JsonNumber::I64(value)) => (*value >= 0).then_some(*value as u64),
248 Self::Number(JsonNumber::U64(value)) => Some(*value),
249 _ => None,
250 }
251 }
252
253 pub fn as_f64(&self) -> Option<f64> {
254 match self {
255 Self::Number(JsonNumber::I64(value)) => Some(*value as f64),
256 Self::Number(JsonNumber::U64(value)) => Some(*value as f64),
257 Self::Number(JsonNumber::F64(value)) => Some(*value),
258 _ => None,
259 }
260 }
261
262 pub fn as_str(&self) -> Option<&str> {
263 match self {
264 Self::String(value) => Some(value.as_str()),
265 _ => None,
266 }
267 }
268
269 pub fn as_array(&self) -> Option<&[JsonValue]> {
270 match self {
271 Self::Array(values) => Some(values.as_slice()),
272 _ => None,
273 }
274 }
275
276 pub fn as_array_mut(&mut self) -> Option<&mut Vec<JsonValue>> {
277 match self {
278 Self::Array(values) => Some(values),
279 _ => None,
280 }
281 }
282
283 pub fn as_object(&self) -> Option<&[(String, JsonValue)]> {
284 match self {
285 Self::Object(entries) => Some(entries.as_slice()),
286 _ => None,
287 }
288 }
289
290 pub fn as_object_mut(&mut self) -> Option<&mut Vec<(String, JsonValue)>> {
291 match self {
292 Self::Object(entries) => Some(entries),
293 _ => None,
294 }
295 }
296
297 pub fn get(&self, key: &str) -> Option<&JsonValue> {
298 match self {
299 Self::Object(entries) => entries.iter().find(|(candidate, _)| candidate == key).map(|(_, value)| value),
300 _ => None,
301 }
302 }
303
304 pub fn get_mut(&mut self, key: &str) -> Option<&mut JsonValue> {
305 match self {
306 Self::Object(entries) => entries.iter_mut().find(|(candidate, _)| candidate == key).map(|(_, value)| value),
307 _ => None,
308 }
309 }
310
311 pub fn len(&self) -> usize {
312 match self {
313 Self::Array(values) => values.len(),
314 Self::Object(entries) => entries.len(),
315 _ => 0,
316 }
317 }
318
319 pub fn is_empty(&self) -> bool {
320 self.len() == 0
321 }
322
323 pub fn as_i128(&self) -> Option<i128> {
324 self.as_i64().map(|v| v as i128)
325 }
326
327 pub fn as_u128(&self) -> Option<u128> {
328 self.as_u64().map(|v| v as u128)
329 }
330
331 pub fn as_f32(&self) -> Option<f32> {
332 self.as_f64().map(|v| v as f32)
333 }
334
335 pub fn get_index(&self, index: usize) -> Option<&JsonValue> {
336 match self {
337 Self::Array(values) => values.get(index),
338 _ => None,
339 }
340 }
341
342 pub fn get_index_mut(&mut self, index: usize) -> Option<&mut JsonValue> {
343 match self {
344 Self::Array(values) => values.get_mut(index),
345 _ => None,
346 }
347 }
348}
349
350impl<'a> BorrowedJsonValue<'a> {
351 pub fn into_owned(self) -> JsonValue {
352 match self {
353 Self::Null => JsonValue::Null,
354 Self::Bool(value) => JsonValue::Bool(value),
355 Self::Number(value) => JsonValue::Number(value),
356 Self::String(value) => JsonValue::String(value.into_owned()),
357 Self::Array(values) => JsonValue::Array(
358 values
359 .into_iter()
360 .map(BorrowedJsonValue::into_owned)
361 .collect(),
362 ),
363 Self::Object(entries) => JsonValue::Object(
364 entries
365 .into_iter()
366 .map(|(key, value)| (key.into_owned(), value.into_owned()))
367 .collect(),
368 ),
369 }
370 }
371}
372
373impl CompiledObjectSchema {
374 pub fn new(keys: &[&str]) -> Self {
375 let mut fields = Vec::with_capacity(keys.len());
376 let mut capacity_hint = 2;
377 for (index, key) in keys.iter().enumerate() {
378 let mut rendered_prefix = Vec::with_capacity(key.len() + 4);
379 if index > 0 {
380 rendered_prefix.push(b',');
381 }
382 write_json_key(&mut rendered_prefix, key);
383 capacity_hint += rendered_prefix.len() + 8;
384 fields.push(CompiledField {
385 key: (*key).to_owned(),
386 rendered_prefix,
387 });
388 }
389 Self {
390 fields,
391 capacity_hint,
392 }
393 }
394
395 pub fn keys(&self) -> impl ExactSizeIterator<Item = &str> {
396 self.fields.iter().map(|field| field.key.as_str())
397 }
398
399 pub fn to_json_string<'a, I>(&self, values: I) -> Result<String, JsonError>
400 where
401 I: IntoIterator<Item = &'a JsonValue>,
402 {
403 let mut out = Vec::with_capacity(self.capacity_hint);
404 self.write_json_bytes(&mut out, values)?;
405 Ok(unsafe { String::from_utf8_unchecked(out) })
406 }
407
408 pub fn write_json_bytes<'a, I>(&self, out: &mut Vec<u8>, values: I) -> Result<(), JsonError>
409 where
410 I: IntoIterator<Item = &'a JsonValue>,
411 {
412 out.push(b'{');
413 let mut iter = values.into_iter();
414 for field in &self.fields {
415 let Some(value) = iter.next() else {
416 panic!(
417 "compiled object schema expected {} values",
418 self.fields.len()
419 );
420 };
421 out.extend_from_slice(&field.rendered_prefix);
422 write_json_value(out, value)?;
423 }
424 if iter.next().is_some() {
425 panic!(
426 "compiled object schema received more than {} values",
427 self.fields.len()
428 );
429 }
430 out.push(b'}');
431 Ok(())
432 }
433}
434
435impl CompiledRowSchema {
436 pub fn new(keys: &[&str]) -> Self {
437 let object = CompiledObjectSchema::new(keys);
438 let row_capacity_hint = object.capacity_hint;
439 Self {
440 object,
441 row_capacity_hint,
442 }
443 }
444
445 pub fn object_schema(&self) -> &CompiledObjectSchema {
446 &self.object
447 }
448
449 pub fn to_json_string<'a, R, I>(&self, rows: R) -> Result<String, JsonError>
450 where
451 R: IntoIterator<Item = I>,
452 I: IntoIterator<Item = &'a JsonValue>,
453 {
454 let iter = rows.into_iter();
455 let (lower, _) = iter.size_hint();
456 let mut out = Vec::with_capacity(2 + lower.saturating_mul(self.row_capacity_hint + 1));
457 self.write_json_bytes_from_iter(&mut out, iter)?;
458 Ok(unsafe { String::from_utf8_unchecked(out) })
459 }
460
461 pub fn write_json_bytes<'a, R, I>(&self, out: &mut Vec<u8>, rows: R) -> Result<(), JsonError>
462 where
463 R: IntoIterator<Item = I>,
464 I: IntoIterator<Item = &'a JsonValue>,
465 {
466 self.write_json_bytes_from_iter(out, rows.into_iter())
467 }
468
469 pub fn write_row_json_bytes<'a, I>(&self, out: &mut Vec<u8>, values: I) -> Result<(), JsonError>
470 where
471 I: IntoIterator<Item = &'a JsonValue>,
472 {
473 self.object.write_json_bytes(out, values)
474 }
475
476 fn write_json_bytes_from_iter<'a, R, I>(
477 &self,
478 out: &mut Vec<u8>,
479 mut rows: R,
480 ) -> Result<(), JsonError>
481 where
482 R: Iterator<Item = I>,
483 I: IntoIterator<Item = &'a JsonValue>,
484 {
485 out.push(b'[');
486 if let Some(first_row) = rows.next() {
487 self.object.write_json_bytes(out, first_row)?;
488 for row in rows {
489 out.push(b',');
490 self.object.write_json_bytes(out, row)?;
491 }
492 }
493 out.push(b']');
494 Ok(())
495 }
496}
497
498impl From<bool> for JsonValue {
499 fn from(value: bool) -> Self {
500 Self::Bool(value)
501 }
502}
503
504impl From<String> for JsonValue {
505 fn from(value: String) -> Self {
506 Self::String(value)
507 }
508}
509
510impl From<&str> for JsonValue {
511 fn from(value: &str) -> Self {
512 Self::String(value.to_owned())
513 }
514}
515
516impl From<i8> for JsonValue {
517 fn from(value: i8) -> Self {
518 Self::Number(JsonNumber::I64(value as i64))
519 }
520}
521
522impl From<i16> for JsonValue {
523 fn from(value: i16) -> Self {
524 Self::Number(JsonNumber::I64(value as i64))
525 }
526}
527
528impl From<i32> for JsonValue {
529 fn from(value: i32) -> Self {
530 Self::Number(JsonNumber::I64(value as i64))
531 }
532}
533
534impl From<i64> for JsonValue {
535 fn from(value: i64) -> Self {
536 Self::Number(JsonNumber::I64(value))
537 }
538}
539
540impl From<isize> for JsonValue {
541 fn from(value: isize) -> Self {
542 Self::Number(JsonNumber::I64(value as i64))
543 }
544}
545
546impl From<u8> for JsonValue {
547 fn from(value: u8) -> Self {
548 Self::Number(JsonNumber::U64(value as u64))
549 }
550}
551
552impl From<u16> for JsonValue {
553 fn from(value: u16) -> Self {
554 Self::Number(JsonNumber::U64(value as u64))
555 }
556}
557
558impl From<u32> for JsonValue {
559 fn from(value: u32) -> Self {
560 Self::Number(JsonNumber::U64(value as u64))
561 }
562}
563
564impl From<u64> for JsonValue {
565 fn from(value: u64) -> Self {
566 Self::Number(JsonNumber::U64(value))
567 }
568}
569
570impl From<usize> for JsonValue {
571 fn from(value: usize) -> Self {
572 Self::Number(JsonNumber::U64(value as u64))
573 }
574}
575
576impl From<f32> for JsonValue {
577 fn from(value: f32) -> Self {
578 Self::Number(JsonNumber::F64(value as f64))
579 }
580}
581
582impl From<f64> for JsonValue {
583 fn from(value: f64) -> Self {
584 Self::Number(JsonNumber::F64(value))
585 }
586}
587
588impl<T> From<Option<T>> for JsonValue
589where
590 T: Into<JsonValue>,
591{
592 fn from(value: Option<T>) -> Self {
593 match value {
594 Some(value) => value.into(),
595 None => Self::Null,
596 }
597 }
598}
599
600impl<T> From<Vec<T>> for JsonValue
601where
602 T: Into<JsonValue>,
603{
604 fn from(values: Vec<T>) -> Self {
605 Self::Array(values.into_iter().map(Into::into).collect())
606 }
607}
608
609
610impl<K, V> std::iter::FromIterator<(K, V)> for JsonValue
611where
612 K: Into<String>,
613 V: Into<JsonValue>,
614{
615 fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
616 Self::Object(
617 iter.into_iter()
618 .map(|(key, value)| (key.into(), value.into()))
619 .collect(),
620 )
621 }
622}
623
624impl<T> std::iter::FromIterator<T> for JsonValue
625where
626 T: Into<JsonValue>,
627{
628 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
629 Self::Array(iter.into_iter().map(Into::into).collect())
630 }
631}
632
633pub fn escape_json_string(input: &str) -> String {
634 let mut out = Vec::with_capacity(input.len() + 2);
635 write_escaped_json_string(&mut out, input);
636 unsafe { String::from_utf8_unchecked(out) }
637}
638
639pub fn parse_json(input: &str) -> Result<JsonValue, JsonParseError> {
640 let mut parser = Parser::new(input);
641 let value = parser.parse_value()?;
642 parser.skip_whitespace();
643 if parser.is_eof() {
644 Ok(value)
645 } else {
646 Err(JsonParseError::UnexpectedTrailingCharacters(parser.index))
647 }
648}
649
650pub fn parse_json_borrowed(input: &str) -> Result<BorrowedJsonValue<'_>, JsonParseError> {
651 let mut parser = Parser::new(input);
652 let value = parser.parse_value_borrowed()?;
653 parser.skip_whitespace();
654 if parser.is_eof() {
655 Ok(value)
656 } else {
657 Err(JsonParseError::UnexpectedTrailingCharacters(parser.index))
658 }
659}
660
661pub fn parse_json_tape(input: &str) -> Result<JsonTape, JsonParseError> {
662 let mut parser = Parser::new(input);
663 let mut tokens = Vec::new();
664 parser.parse_tape_value(&mut tokens, None)?;
665 parser.skip_whitespace();
666 if parser.is_eof() {
667 Ok(JsonTape { tokens })
668 } else {
669 Err(JsonParseError::UnexpectedTrailingCharacters(parser.index))
670 }
671}
672
673
674pub fn from_str(input: &str) -> Result<JsonValue, JsonParseError> {
675 parse_json(input)
676}
677
678pub fn from_slice(input: &[u8]) -> Result<JsonValue, JsonParseError> {
679 let input = std::str::from_utf8(input).map_err(|_| JsonParseError::InvalidUtf8)?;
680 parse_json(input)
681}
682
683pub fn to_string(value: &JsonValue) -> Result<String, JsonError> {
684 value.to_json_string()
685}
686
687pub fn to_vec(value: &JsonValue) -> Result<Vec<u8>, JsonError> {
688 let mut out = Vec::with_capacity(initial_json_capacity(value));
689 write_json_value(&mut out, value)?;
690 Ok(out)
691}
692
693pub fn from_reader<R: Read>(mut reader: R) -> Result<JsonValue, JsonParseError> {
694 let mut input = String::new();
695 reader
696 .read_to_string(&mut input)
697 .map_err(|_| JsonParseError::InvalidUtf8)?;
698 parse_json(&input)
699}
700
701pub fn to_writer<W: Write>(mut writer: W, value: &JsonValue) -> Result<(), JsonError> {
702 let bytes = to_vec(value)?;
703 writer.write_all(&bytes).map_err(|_| JsonError::Io)
704}
705
706impl JsonTape {
707 pub fn root<'a>(&'a self, input: &'a str) -> Option<TapeValue<'a>> {
708 (!self.tokens.is_empty()).then_some(TapeValue {
709 tape: self,
710 input,
711 index: 0,
712 })
713 }
714}
715
716impl<'a> TapeValue<'a> {
717 pub fn kind(&self) -> TapeTokenKind {
718 self.tape.tokens[self.index].kind
719 }
720
721 pub fn as_str(&self) -> Option<&'a str> {
722 let token = &self.tape.tokens[self.index];
723 match token.kind {
724 TapeTokenKind::String | TapeTokenKind::Key => {
725 if self.input.as_bytes()[token.start] == b'"'
726 && self.input.as_bytes()[token.end - 1] == b'"'
727 {
728 Some(&self.input[token.start + 1..token.end - 1])
729 } else {
730 None
731 }
732 }
733 _ => None,
734 }
735 }
736
737 pub fn get(&self, key: &str) -> Option<TapeValue<'a>> {
738 if self.kind() != TapeTokenKind::Object {
739 return None;
740 }
741 self.get_linear(key)
742 }
743
744 pub fn build_object_index(&self) -> Option<TapeObjectIndex> {
745 if self.kind() != TapeTokenKind::Object {
746 return None;
747 }
748 let parent = self.index;
749 let tokens = &self.tape.tokens;
750 let mut entries = Vec::new();
751 let mut i = self.index + 1;
752 while i + 1 < tokens.len() {
753 if tokens[i].parent != Some(parent) {
754 i += 1;
755 continue;
756 }
757 if tokens[i].kind == TapeTokenKind::Key && tokens[i + 1].parent == Some(parent) {
758 let candidate = TapeValue {
759 tape: self.tape,
760 input: self.input,
761 index: i,
762 };
763 let key = candidate.as_str().unwrap_or("");
764 let hash = hash_key(key.as_bytes());
765 entries.push((hash, i, i + 1));
766 i += 2;
767 } else {
768 i += 1;
769 }
770 }
771 let bucket_count = (entries.len().next_power_of_two().max(1)) * 2;
772 let mut buckets = vec![Vec::new(); bucket_count];
773 for entry in entries {
774 let bucket = (entry.0 as usize) & (bucket_count - 1);
775 buckets[bucket].push(entry);
776 }
777 Some(TapeObjectIndex { buckets })
778 }
779
780 pub fn with_index<'b>(&'b self, index: &'b TapeObjectIndex) -> IndexedTapeObject<'b> {
781 IndexedTapeObject {
782 object: TapeValue {
783 tape: self.tape,
784 input: self.input,
785 index: self.index,
786 },
787 index,
788 }
789 }
790
791 fn get_linear(&self, key: &str) -> Option<TapeValue<'a>> {
792 let parent = self.index;
793 let tokens = &self.tape.tokens;
794 let mut i = self.index + 1;
795 while i < tokens.len() {
796 if tokens[i].parent != Some(parent) {
797 i += 1;
798 continue;
799 }
800 if tokens[i].kind != TapeTokenKind::Key {
801 i += 1;
802 continue;
803 }
804 let candidate = TapeValue {
805 tape: self.tape,
806 input: self.input,
807 index: i,
808 };
809 if candidate.as_str() == Some(key) {
810 let value_index = i + 1;
811 if value_index < tokens.len() && tokens[value_index].parent == Some(parent) {
812 return Some(TapeValue {
813 tape: self.tape,
814 input: self.input,
815 index: value_index,
816 });
817 }
818 return None;
819 }
820 i += 1;
821 }
822 None
823 }
824}
825
826impl TapeObjectIndex {
827 pub fn get<'a>(&self, object: TapeValue<'a>, key: &str) -> Option<TapeValue<'a>> {
828 self.get_hashed(object, hash_key(key.as_bytes()), key)
829 }
830
831 pub fn get_compiled<'a>(&self, object: TapeValue<'a>, key: &CompiledTapeKey) -> Option<TapeValue<'a>> {
832 self.get_hashed(object, key.hash, &key.key)
833 }
834
835 fn get_hashed<'a>(&self, object: TapeValue<'a>, hash: u64, key: &str) -> Option<TapeValue<'a>> {
836 let bucket = (hash as usize) & (self.buckets.len() - 1);
837 for (entry_hash, key_index, value_index) in &self.buckets[bucket] {
838 if *entry_hash != hash {
839 continue;
840 }
841 let candidate = TapeValue {
842 tape: object.tape,
843 input: object.input,
844 index: *key_index,
845 };
846 if candidate.as_str() == Some(key) {
847 return Some(TapeValue {
848 tape: object.tape,
849 input: object.input,
850 index: *value_index,
851 });
852 }
853 }
854 None
855 }
856}
857
858impl CompiledTapeKey {
859 pub fn new(key: impl Into<String>) -> Self {
860 let key = key.into();
861 let hash = hash_key(key.as_bytes());
862 Self { key, hash }
863 }
864
865 pub fn as_str(&self) -> &str {
866 &self.key
867 }
868}
869
870impl CompiledTapeKeys {
871 pub fn new(keys: &[&str]) -> Self {
872 Self {
873 keys: keys.iter().map(|key| CompiledTapeKey::new(*key)).collect(),
874 }
875 }
876
877 pub fn iter(&self) -> impl Iterator<Item = &CompiledTapeKey> {
878 self.keys.iter()
879 }
880}
881
882impl<'a> IndexedTapeObject<'a> {
883 pub fn get(&self, key: &str) -> Option<TapeValue<'a>> {
884 self.index.get(self.object, key)
885 }
886
887 pub fn get_compiled(&self, key: &CompiledTapeKey) -> Option<TapeValue<'a>> {
888 self.index.get_compiled(self.object, key)
889 }
890
891 pub fn get_many<'b>(
892 &'b self,
893 keys: &'b [&'b str],
894 ) -> impl Iterator<Item = Option<TapeValue<'a>>> + 'b {
895 keys.iter().map(|key| self.get(key))
896 }
897
898 pub fn get_compiled_many<'b>(
899 &'b self,
900 keys: &'b CompiledTapeKeys,
901 ) -> impl Iterator<Item = Option<TapeValue<'a>>> + 'b {
902 keys.iter().map(|key| self.get_compiled(key))
903 }
904}
905
906
907impl fmt::Display for JsonValue {
908 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
909 match self.to_json_string() {
910 Ok(json) => f.write_str(&json),
911 Err(_) => Err(fmt::Error),
912 }
913 }
914}
915
916static JSON_NULL: JsonValue = JsonValue::Null;
917
918impl Index<&str> for JsonValue {
919 type Output = JsonValue;
920
921 fn index(&self, index: &str) -> &Self::Output {
922 self.get(index).unwrap_or(&JSON_NULL)
923 }
924}
925
926impl Index<usize> for JsonValue {
927 type Output = JsonValue;
928
929 fn index(&self, index: usize) -> &Self::Output {
930 match self {
931 JsonValue::Array(values) => values.get(index).unwrap_or(&JSON_NULL),
932 _ => &JSON_NULL,
933 }
934 }
935}
936
937#[macro_export]
938macro_rules! json {
939 (null) => {
940 $crate::JsonValue::Null
941 };
942 ([$($element:tt),* $(,)?]) => {
943 $crate::JsonValue::Array(vec![$($crate::json!($element)),*])
944 };
945 ({$($key:literal : $value:tt),* $(,)?}) => {
946 $crate::JsonValue::Object(vec![$(($key.to_owned(), $crate::json!($value))),*])
947 };
948 ($other:expr) => {
949 $crate::JsonValue::from($other)
950 };
951}
952
953fn hash_key(bytes: &[u8]) -> u64 {
954 let mut hash = 1469598103934665603u64;
955 for &byte in bytes {
956 hash ^= byte as u64;
957 hash = hash.wrapping_mul(1099511628211u64);
958 }
959 hash
960}
961
962#[inline]
963fn write_json_value(out: &mut Vec<u8>, value: &JsonValue) -> Result<(), JsonError> {
964 match value {
965 JsonValue::Null => out.extend_from_slice(b"null"),
966 JsonValue::Bool(value) => {
967 if *value {
968 out.extend_from_slice(b"true");
969 } else {
970 out.extend_from_slice(b"false");
971 }
972 }
973 JsonValue::Number(number) => write_json_number(out, number)?,
974 JsonValue::String(value) => {
975 write_escaped_json_string(out, value);
976 }
977 JsonValue::Array(values) => {
978 write_json_array(out, values)?;
979 }
980 JsonValue::Object(entries) => {
981 write_json_object(out, entries)?;
982 }
983 }
984 Ok(())
985}
986
987#[inline]
988fn write_json_number(out: &mut Vec<u8>, value: &JsonNumber) -> Result<(), JsonError> {
989 match value {
990 JsonNumber::I64(value) => {
991 append_i64(out, *value);
992 Ok(())
993 }
994 JsonNumber::U64(value) => {
995 append_u64(out, *value);
996 Ok(())
997 }
998 JsonNumber::F64(value) => {
999 if !value.is_finite() {
1000 return Err(JsonError::NonFiniteNumber);
1001 }
1002 out.extend_from_slice(value.to_string().as_bytes());
1003 Ok(())
1004 }
1005 }
1006}
1007
1008#[inline]
1009fn write_escaped_json_string(out: &mut Vec<u8>, input: &str) {
1010 out.push(b'"');
1011 let bytes = input.as_bytes();
1012 let mut fast_index = 0usize;
1013 while fast_index < bytes.len() {
1014 let byte = bytes[fast_index];
1015 if needs_escape(byte) {
1016 break;
1017 }
1018 fast_index += 1;
1019 }
1020 if fast_index == bytes.len() {
1021 out.extend_from_slice(bytes);
1022 out.push(b'"');
1023 return;
1024 }
1025
1026 if fast_index > 0 {
1027 out.extend_from_slice(&bytes[..fast_index]);
1028 }
1029
1030 let mut chunk_start = fast_index;
1031 for (index, byte) in bytes.iter().copied().enumerate().skip(fast_index) {
1032 let escape = match byte {
1033 b'"' => Some(br#"\""#.as_slice()),
1034 b'\\' => Some(br#"\\"#.as_slice()),
1035 0x08 => Some(br#"\b"#.as_slice()),
1036 0x0c => Some(br#"\f"#.as_slice()),
1037 b'\n' => Some(br#"\n"#.as_slice()),
1038 b'\r' => Some(br#"\r"#.as_slice()),
1039 b'\t' => Some(br#"\t"#.as_slice()),
1040 _ => None,
1041 };
1042 if let Some(escape) = escape {
1043 if chunk_start < index {
1044 out.extend_from_slice(&bytes[chunk_start..index]);
1045 }
1046 out.extend_from_slice(escape);
1047 chunk_start = index + 1;
1048 continue;
1049 }
1050 if byte <= 0x1f {
1051 if chunk_start < index {
1052 out.extend_from_slice(&bytes[chunk_start..index]);
1053 }
1054 out.extend_from_slice(br#"\u00"#);
1055 out.push(hex_digit((byte >> 4) & 0x0f));
1056 out.push(hex_digit(byte & 0x0f));
1057 chunk_start = index + 1;
1058 }
1059 }
1060 if chunk_start < input.len() {
1061 out.extend_from_slice(&bytes[chunk_start..]);
1062 }
1063 out.push(b'"');
1064}
1065
1066#[inline]
1067fn needs_escape(byte: u8) -> bool {
1068 matches!(byte, b'"' | b'\\' | 0x00..=0x1f)
1069}
1070
1071#[inline]
1072fn write_json_array(out: &mut Vec<u8>, values: &[JsonValue]) -> Result<(), JsonError> {
1073 out.push(b'[');
1074 match values {
1075 [] => {}
1076 [one] => {
1077 write_json_value(out, one)?;
1078 }
1079 [a, b] => {
1080 write_json_value(out, a)?;
1081 out.push(b',');
1082 write_json_value(out, b)?;
1083 }
1084 [a, b, c] => {
1085 write_json_value(out, a)?;
1086 out.push(b',');
1087 write_json_value(out, b)?;
1088 out.push(b',');
1089 write_json_value(out, c)?;
1090 }
1091 _ => {
1092 let mut iter = values.iter();
1093 if let Some(first) = iter.next() {
1094 write_json_value(out, first)?;
1095 for value in iter {
1096 out.push(b',');
1097 write_json_value(out, value)?;
1098 }
1099 }
1100 }
1101 }
1102 out.push(b']');
1103 Ok(())
1104}
1105
1106#[inline]
1107fn write_json_object(out: &mut Vec<u8>, entries: &[(String, JsonValue)]) -> Result<(), JsonError> {
1108 out.push(b'{');
1109 match entries {
1110 [] => {}
1111 [(k1, v1)] => {
1112 write_json_key(out, k1);
1113 write_json_value(out, v1)?;
1114 }
1115 [(k1, v1), (k2, v2)] => {
1116 write_json_key(out, k1);
1117 write_json_value(out, v1)?;
1118 out.push(b',');
1119 write_json_key(out, k2);
1120 write_json_value(out, v2)?;
1121 }
1122 [(k1, v1), (k2, v2), (k3, v3)] => {
1123 write_json_key(out, k1);
1124 write_json_value(out, v1)?;
1125 out.push(b',');
1126 write_json_key(out, k2);
1127 write_json_value(out, v2)?;
1128 out.push(b',');
1129 write_json_key(out, k3);
1130 write_json_value(out, v3)?;
1131 }
1132 _ => {
1133 let mut iter = entries.iter();
1134 if let Some((first_key, first_value)) = iter.next() {
1135 write_json_key(out, first_key);
1136 write_json_value(out, first_value)?;
1137 for (key, value) in iter {
1138 out.push(b',');
1139 write_json_key(out, key);
1140 write_json_value(out, value)?;
1141 }
1142 }
1143 }
1144 }
1145 out.push(b'}');
1146 Ok(())
1147}
1148
1149#[inline]
1150fn write_json_key(out: &mut Vec<u8>, key: &str) {
1151 let bytes = key.as_bytes();
1152 if is_plain_json_string(bytes) {
1153 out.push(b'"');
1154 out.extend_from_slice(bytes);
1155 out.extend_from_slice(b"\":");
1156 } else {
1157 write_escaped_json_string(out, key);
1158 out.push(b':');
1159 }
1160}
1161
1162#[inline]
1163fn is_plain_json_string(bytes: &[u8]) -> bool {
1164 for &byte in bytes {
1165 if needs_escape(byte) {
1166 return false;
1167 }
1168 }
1169 true
1170}
1171
1172fn initial_json_capacity(value: &JsonValue) -> usize {
1173 match value {
1174 JsonValue::Null => 4,
1175 JsonValue::Bool(true) => 4,
1176 JsonValue::Bool(false) => 5,
1177 JsonValue::Number(JsonNumber::I64(value)) => estimate_i64_len(*value),
1178 JsonValue::Number(JsonNumber::U64(value)) => estimate_u64_len(*value),
1179 JsonValue::Number(JsonNumber::F64(_)) => 24,
1180 JsonValue::String(value) => estimate_escaped_string_len(value),
1181 JsonValue::Array(values) => 2 + values.len().saturating_mul(16),
1182 JsonValue::Object(entries) => {
1183 2 + entries
1184 .iter()
1185 .map(|(key, _)| estimate_escaped_string_len(key) + 8)
1186 .sum::<usize>()
1187 }
1188 }
1189}
1190
1191fn estimate_escaped_string_len(value: &str) -> usize {
1192 let mut len = 2;
1193 for ch in value.chars() {
1194 len += match ch {
1195 '"' | '\\' | '\u{08}' | '\u{0C}' | '\n' | '\r' | '\t' => 2,
1196 ch if ch <= '\u{1F}' => 6,
1197 ch => ch.len_utf8(),
1198 };
1199 }
1200 len
1201}
1202
1203fn estimate_u64_len(mut value: u64) -> usize {
1204 let mut len = 1;
1205 while value >= 10 {
1206 value /= 10;
1207 len += 1;
1208 }
1209 len
1210}
1211
1212fn estimate_i64_len(value: i64) -> usize {
1213 if value < 0 {
1214 1 + estimate_u64_len(value.unsigned_abs())
1215 } else {
1216 estimate_u64_len(value as u64)
1217 }
1218}
1219
1220fn append_i64(out: &mut Vec<u8>, value: i64) {
1221 if value < 0 {
1222 out.push(b'-');
1223 append_u64(out, value.unsigned_abs());
1224 } else {
1225 append_u64(out, value as u64);
1226 }
1227}
1228
1229fn append_u64(out: &mut Vec<u8>, mut value: u64) {
1230 let mut buf = [0u8; 20];
1231 let mut index = buf.len();
1232 loop {
1233 index -= 1;
1234 buf[index] = b'0' + (value % 10) as u8;
1235 value /= 10;
1236 if value == 0 {
1237 break;
1238 }
1239 }
1240 out.extend_from_slice(&buf[index..]);
1241}
1242
1243fn hex_digit(value: u8) -> u8 {
1244 match value {
1245 0..=9 => b'0' + value,
1246 10..=15 => b'a' + (value - 10),
1247 _ => unreachable!(),
1248 }
1249}
1250
1251struct Parser<'a> {
1252 input: &'a str,
1253 bytes: &'a [u8],
1254 index: usize,
1255}
1256
1257impl<'a> Parser<'a> {
1258 fn new(input: &'a str) -> Self {
1259 Self {
1260 input,
1261 bytes: input.as_bytes(),
1262 index: 0,
1263 }
1264 }
1265
1266 fn parse_value(&mut self) -> Result<JsonValue, JsonParseError> {
1267 self.skip_whitespace();
1268 match self.peek_byte() {
1269 Some(b'n') => self.parse_literal(b"null", JsonValue::Null),
1270 Some(b't') => self.parse_literal(b"true", JsonValue::Bool(true)),
1271 Some(b'f') => self.parse_literal(b"false", JsonValue::Bool(false)),
1272 Some(b'"') => Ok(JsonValue::String(self.parse_string()?)),
1273 Some(b'[') => self.parse_array(),
1274 Some(b'{') => self.parse_object(),
1275 Some(b'-' | b'0'..=b'9') => self.parse_number().map(JsonValue::Number),
1276 Some(found) => Err(JsonParseError::UnexpectedCharacter {
1277 index: self.index,
1278 found: found as char,
1279 }),
1280 None => Err(JsonParseError::UnexpectedEnd),
1281 }
1282 }
1283
1284 fn parse_value_borrowed(&mut self) -> Result<BorrowedJsonValue<'a>, JsonParseError> {
1285 self.skip_whitespace();
1286 match self.peek_byte() {
1287 Some(b'n') => self.parse_literal_borrowed(b"null", BorrowedJsonValue::Null),
1288 Some(b't') => self.parse_literal_borrowed(b"true", BorrowedJsonValue::Bool(true)),
1289 Some(b'f') => self.parse_literal_borrowed(b"false", BorrowedJsonValue::Bool(false)),
1290 Some(b'"') => Ok(BorrowedJsonValue::String(self.parse_string_borrowed()?)),
1291 Some(b'[') => self.parse_array_borrowed(),
1292 Some(b'{') => self.parse_object_borrowed(),
1293 Some(b'-' | b'0'..=b'9') => self.parse_number().map(BorrowedJsonValue::Number),
1294 Some(found) => Err(JsonParseError::UnexpectedCharacter {
1295 index: self.index,
1296 found: found as char,
1297 }),
1298 None => Err(JsonParseError::UnexpectedEnd),
1299 }
1300 }
1301
1302 fn parse_tape_value(
1303 &mut self,
1304 tokens: &mut Vec<TapeToken>,
1305 parent: Option<usize>,
1306 ) -> Result<usize, JsonParseError> {
1307 self.skip_whitespace();
1308 match self.peek_byte() {
1309 Some(b'n') => self.parse_tape_literal(tokens, parent, b"null", TapeTokenKind::Null),
1310 Some(b't') => self.parse_tape_literal(tokens, parent, b"true", TapeTokenKind::Bool),
1311 Some(b'f') => self.parse_tape_literal(tokens, parent, b"false", TapeTokenKind::Bool),
1312 Some(b'"') => self.parse_tape_string(tokens, parent, TapeTokenKind::String),
1313 Some(b'[') => self.parse_tape_array(tokens, parent),
1314 Some(b'{') => self.parse_tape_object(tokens, parent),
1315 Some(b'-' | b'0'..=b'9') => self.parse_tape_number(tokens, parent),
1316 Some(found) => Err(JsonParseError::UnexpectedCharacter {
1317 index: self.index,
1318 found: found as char,
1319 }),
1320 None => Err(JsonParseError::UnexpectedEnd),
1321 }
1322 }
1323
1324 fn parse_literal(
1325 &mut self,
1326 expected: &[u8],
1327 value: JsonValue,
1328 ) -> Result<JsonValue, JsonParseError> {
1329 if self.bytes[self.index..].starts_with(expected) {
1330 self.index += expected.len();
1331 Ok(value)
1332 } else {
1333 Err(JsonParseError::InvalidLiteral { index: self.index })
1334 }
1335 }
1336
1337 fn parse_literal_borrowed(
1338 &mut self,
1339 expected: &[u8],
1340 value: BorrowedJsonValue<'a>,
1341 ) -> Result<BorrowedJsonValue<'a>, JsonParseError> {
1342 if self.bytes[self.index..].starts_with(expected) {
1343 self.index += expected.len();
1344 Ok(value)
1345 } else {
1346 Err(JsonParseError::InvalidLiteral { index: self.index })
1347 }
1348 }
1349
1350 fn parse_tape_literal(
1351 &mut self,
1352 tokens: &mut Vec<TapeToken>,
1353 parent: Option<usize>,
1354 expected: &[u8],
1355 kind: TapeTokenKind,
1356 ) -> Result<usize, JsonParseError> {
1357 let start = self.index;
1358 if self.bytes[self.index..].starts_with(expected) {
1359 self.index += expected.len();
1360 let token_index = tokens.len();
1361 tokens.push(TapeToken {
1362 kind,
1363 start,
1364 end: self.index,
1365 parent,
1366 });
1367 Ok(token_index)
1368 } else {
1369 Err(JsonParseError::InvalidLiteral { index: self.index })
1370 }
1371 }
1372
1373 fn parse_array(&mut self) -> Result<JsonValue, JsonParseError> {
1374 self.consume_byte(b'[')?;
1375 self.skip_whitespace();
1376 let mut values = Vec::new();
1377 if self.try_consume_byte(b']') {
1378 return Ok(JsonValue::Array(values));
1379 }
1380 loop {
1381 values.push(self.parse_value()?);
1382 self.skip_whitespace();
1383 if self.try_consume_byte(b']') {
1384 break;
1385 }
1386 if !self.try_consume_byte(b',') {
1387 return Err(JsonParseError::ExpectedCommaOrEnd {
1388 index: self.index,
1389 context: "array",
1390 });
1391 }
1392 self.skip_whitespace();
1393 }
1394 Ok(JsonValue::Array(values))
1395 }
1396
1397 fn parse_array_borrowed(&mut self) -> Result<BorrowedJsonValue<'a>, JsonParseError> {
1398 self.consume_byte(b'[')?;
1399 self.skip_whitespace();
1400 let mut values = Vec::new();
1401 if self.try_consume_byte(b']') {
1402 return Ok(BorrowedJsonValue::Array(values));
1403 }
1404 loop {
1405 values.push(self.parse_value_borrowed()?);
1406 self.skip_whitespace();
1407 if self.try_consume_byte(b']') {
1408 break;
1409 }
1410 if !self.try_consume_byte(b',') {
1411 return Err(JsonParseError::ExpectedCommaOrEnd {
1412 index: self.index,
1413 context: "array",
1414 });
1415 }
1416 self.skip_whitespace();
1417 }
1418 Ok(BorrowedJsonValue::Array(values))
1419 }
1420
1421 fn parse_tape_array(
1422 &mut self,
1423 tokens: &mut Vec<TapeToken>,
1424 parent: Option<usize>,
1425 ) -> Result<usize, JsonParseError> {
1426 let start = self.index;
1427 self.consume_byte(b'[')?;
1428 let token_index = tokens.len();
1429 tokens.push(TapeToken {
1430 kind: TapeTokenKind::Array,
1431 start,
1432 end: start,
1433 parent,
1434 });
1435 self.skip_whitespace();
1436 if self.try_consume_byte(b']') {
1437 tokens[token_index].end = self.index;
1438 return Ok(token_index);
1439 }
1440 loop {
1441 self.parse_tape_value(tokens, Some(token_index))?;
1442 self.skip_whitespace();
1443 if self.try_consume_byte(b']') {
1444 tokens[token_index].end = self.index;
1445 break;
1446 }
1447 if !self.try_consume_byte(b',') {
1448 return Err(JsonParseError::ExpectedCommaOrEnd {
1449 index: self.index,
1450 context: "array",
1451 });
1452 }
1453 self.skip_whitespace();
1454 }
1455 Ok(token_index)
1456 }
1457
1458 fn parse_object(&mut self) -> Result<JsonValue, JsonParseError> {
1459 self.consume_byte(b'{')?;
1460 self.skip_whitespace();
1461 let mut entries = Vec::new();
1462 if self.try_consume_byte(b'}') {
1463 return Ok(JsonValue::Object(entries));
1464 }
1465 loop {
1466 if self.peek_byte() != Some(b'"') {
1467 return match self.peek_byte() {
1468 Some(found) => Err(JsonParseError::UnexpectedCharacter {
1469 index: self.index,
1470 found: found as char,
1471 }),
1472 None => Err(JsonParseError::UnexpectedEnd),
1473 };
1474 }
1475 let key = self.parse_string()?;
1476 self.skip_whitespace();
1477 if !self.try_consume_byte(b':') {
1478 return Err(JsonParseError::ExpectedColon { index: self.index });
1479 }
1480 let value = self.parse_value()?;
1481 entries.push((key, value));
1482 self.skip_whitespace();
1483 if self.try_consume_byte(b'}') {
1484 break;
1485 }
1486 if !self.try_consume_byte(b',') {
1487 return Err(JsonParseError::ExpectedCommaOrEnd {
1488 index: self.index,
1489 context: "object",
1490 });
1491 }
1492 self.skip_whitespace();
1493 }
1494 Ok(JsonValue::Object(entries))
1495 }
1496
1497 fn parse_object_borrowed(&mut self) -> Result<BorrowedJsonValue<'a>, JsonParseError> {
1498 self.consume_byte(b'{')?;
1499 self.skip_whitespace();
1500 let mut entries = Vec::new();
1501 if self.try_consume_byte(b'}') {
1502 return Ok(BorrowedJsonValue::Object(entries));
1503 }
1504 loop {
1505 if self.peek_byte() != Some(b'"') {
1506 return match self.peek_byte() {
1507 Some(found) => Err(JsonParseError::UnexpectedCharacter {
1508 index: self.index,
1509 found: found as char,
1510 }),
1511 None => Err(JsonParseError::UnexpectedEnd),
1512 };
1513 }
1514 let key = self.parse_string_borrowed()?;
1515 self.skip_whitespace();
1516 if !self.try_consume_byte(b':') {
1517 return Err(JsonParseError::ExpectedColon { index: self.index });
1518 }
1519 let value = self.parse_value_borrowed()?;
1520 entries.push((key, value));
1521 self.skip_whitespace();
1522 if self.try_consume_byte(b'}') {
1523 break;
1524 }
1525 if !self.try_consume_byte(b',') {
1526 return Err(JsonParseError::ExpectedCommaOrEnd {
1527 index: self.index,
1528 context: "object",
1529 });
1530 }
1531 self.skip_whitespace();
1532 }
1533 Ok(BorrowedJsonValue::Object(entries))
1534 }
1535
1536 fn parse_tape_object(
1537 &mut self,
1538 tokens: &mut Vec<TapeToken>,
1539 parent: Option<usize>,
1540 ) -> Result<usize, JsonParseError> {
1541 let start = self.index;
1542 self.consume_byte(b'{')?;
1543 let token_index = tokens.len();
1544 tokens.push(TapeToken {
1545 kind: TapeTokenKind::Object,
1546 start,
1547 end: start,
1548 parent,
1549 });
1550 self.skip_whitespace();
1551 if self.try_consume_byte(b'}') {
1552 tokens[token_index].end = self.index;
1553 return Ok(token_index);
1554 }
1555 loop {
1556 if self.peek_byte() != Some(b'"') {
1557 return match self.peek_byte() {
1558 Some(found) => Err(JsonParseError::UnexpectedCharacter {
1559 index: self.index,
1560 found: found as char,
1561 }),
1562 None => Err(JsonParseError::UnexpectedEnd),
1563 };
1564 }
1565 self.parse_tape_string(tokens, Some(token_index), TapeTokenKind::Key)?;
1566 self.skip_whitespace();
1567 if !self.try_consume_byte(b':') {
1568 return Err(JsonParseError::ExpectedColon { index: self.index });
1569 }
1570 self.parse_tape_value(tokens, Some(token_index))?;
1571 self.skip_whitespace();
1572 if self.try_consume_byte(b'}') {
1573 tokens[token_index].end = self.index;
1574 break;
1575 }
1576 if !self.try_consume_byte(b',') {
1577 return Err(JsonParseError::ExpectedCommaOrEnd {
1578 index: self.index,
1579 context: "object",
1580 });
1581 }
1582 self.skip_whitespace();
1583 }
1584 Ok(token_index)
1585 }
1586
1587 fn parse_string(&mut self) -> Result<String, JsonParseError> {
1588 self.consume_byte(b'"')?;
1589 let start = self.index;
1590 loop {
1591 let Some(byte) = self.next_byte() else {
1592 return Err(JsonParseError::UnexpectedEnd);
1593 };
1594 match byte {
1595 b'"' => {
1596 let slice = &self.input[start..self.index - 1];
1597 return Ok(slice.to_owned());
1598 }
1599 b'\\' => {
1600 let mut out = String::with_capacity(self.index - start + 8);
1601 out.push_str(&self.input[start..self.index - 1]);
1602 self.parse_escape_into(&mut out, self.index - 1)?;
1603 return self.parse_string_slow(out);
1604 }
1605 0x00..=0x1f => {
1606 return Err(JsonParseError::UnexpectedCharacter {
1607 index: self.index - 1,
1608 found: byte as char,
1609 })
1610 }
1611 _ => {}
1612 }
1613 }
1614 }
1615
1616 fn parse_string_borrowed(&mut self) -> Result<Cow<'a, str>, JsonParseError> {
1617 self.consume_byte(b'"')?;
1618 let start = self.index;
1619 loop {
1620 let Some(byte) = self.next_byte() else {
1621 return Err(JsonParseError::UnexpectedEnd);
1622 };
1623 match byte {
1624 b'"' => {
1625 let slice = &self.input[start..self.index - 1];
1626 return Ok(Cow::Borrowed(slice));
1627 }
1628 b'\\' => {
1629 let mut out = String::with_capacity(self.index - start + 8);
1630 out.push_str(&self.input[start..self.index - 1]);
1631 self.parse_escape_into(&mut out, self.index - 1)?;
1632 return self.parse_string_slow_borrowed(out);
1633 }
1634 0x00..=0x1f => {
1635 return Err(JsonParseError::UnexpectedCharacter {
1636 index: self.index - 1,
1637 found: byte as char,
1638 })
1639 }
1640 _ => {}
1641 }
1642 }
1643 }
1644
1645 fn parse_tape_string(
1646 &mut self,
1647 tokens: &mut Vec<TapeToken>,
1648 parent: Option<usize>,
1649 kind: TapeTokenKind,
1650 ) -> Result<usize, JsonParseError> {
1651 let start = self.index;
1652 self.skip_string_bytes()?;
1653 let token_index = tokens.len();
1654 tokens.push(TapeToken {
1655 kind,
1656 start,
1657 end: self.index,
1658 parent,
1659 });
1660 Ok(token_index)
1661 }
1662
1663 fn skip_string_bytes(&mut self) -> Result<(), JsonParseError> {
1664 self.consume_byte(b'"')?;
1665 loop {
1666 let Some(byte) = self.next_byte() else {
1667 return Err(JsonParseError::UnexpectedEnd);
1668 };
1669 match byte {
1670 b'"' => return Ok(()),
1671 b'\\' => {
1672 let escape_index = self.index - 1;
1673 let escaped = self.next_byte().ok_or(JsonParseError::UnexpectedEnd)?;
1674 match escaped {
1675 b'"' | b'\\' | b'/' | b'b' | b'f' | b'n' | b'r' | b't' => {}
1676 b'u' => {
1677 let scalar = self.parse_hex_quad(escape_index)?;
1678 if (0xD800..=0xDBFF).contains(&scalar) {
1679 if self.next_byte() != Some(b'\\') || self.next_byte() != Some(b'u')
1680 {
1681 return Err(JsonParseError::InvalidUnicodeScalar {
1682 index: escape_index,
1683 });
1684 }
1685 let low = self.parse_hex_quad(escape_index)?;
1686 if !(0xDC00..=0xDFFF).contains(&low) {
1687 return Err(JsonParseError::InvalidUnicodeScalar {
1688 index: escape_index,
1689 });
1690 }
1691 } else if (0xDC00..=0xDFFF).contains(&scalar) {
1692 return Err(JsonParseError::InvalidUnicodeScalar {
1693 index: escape_index,
1694 });
1695 }
1696 }
1697 _ => {
1698 return Err(JsonParseError::InvalidEscape {
1699 index: escape_index,
1700 })
1701 }
1702 }
1703 }
1704 0x00..=0x1f => {
1705 return Err(JsonParseError::UnexpectedCharacter {
1706 index: self.index - 1,
1707 found: byte as char,
1708 })
1709 }
1710 _ => {}
1711 }
1712 }
1713 }
1714
1715 fn parse_string_slow(&mut self, mut out: String) -> Result<String, JsonParseError> {
1716 let mut chunk_start = self.index;
1717 loop {
1718 let Some(byte) = self.next_byte() else {
1719 return Err(JsonParseError::UnexpectedEnd);
1720 };
1721 match byte {
1722 b'"' => {
1723 if chunk_start < self.index - 1 {
1724 out.push_str(&self.input[chunk_start..self.index - 1]);
1725 }
1726 return Ok(out);
1727 }
1728 b'\\' => {
1729 if chunk_start < self.index - 1 {
1730 out.push_str(&self.input[chunk_start..self.index - 1]);
1731 }
1732 self.parse_escape_into(&mut out, self.index - 1)?;
1733 chunk_start = self.index;
1734 }
1735 0x00..=0x1f => {
1736 return Err(JsonParseError::UnexpectedCharacter {
1737 index: self.index - 1,
1738 found: byte as char,
1739 })
1740 }
1741 _ => {}
1742 }
1743 }
1744 }
1745
1746 fn parse_string_slow_borrowed(
1747 &mut self,
1748 mut out: String,
1749 ) -> Result<Cow<'a, str>, JsonParseError> {
1750 let mut chunk_start = self.index;
1751 loop {
1752 let Some(byte) = self.next_byte() else {
1753 return Err(JsonParseError::UnexpectedEnd);
1754 };
1755 match byte {
1756 b'"' => {
1757 if chunk_start < self.index - 1 {
1758 out.push_str(&self.input[chunk_start..self.index - 1]);
1759 }
1760 return Ok(Cow::Owned(out));
1761 }
1762 b'\\' => {
1763 if chunk_start < self.index - 1 {
1764 out.push_str(&self.input[chunk_start..self.index - 1]);
1765 }
1766 self.parse_escape_into(&mut out, self.index - 1)?;
1767 chunk_start = self.index;
1768 }
1769 0x00..=0x1f => {
1770 return Err(JsonParseError::UnexpectedCharacter {
1771 index: self.index - 1,
1772 found: byte as char,
1773 })
1774 }
1775 _ => {}
1776 }
1777 }
1778 }
1779
1780 fn parse_escape_into(
1781 &mut self,
1782 out: &mut String,
1783 escape_index: usize,
1784 ) -> Result<(), JsonParseError> {
1785 let escaped = self.next_byte().ok_or(JsonParseError::UnexpectedEnd)?;
1786 match escaped {
1787 b'"' => out.push('"'),
1788 b'\\' => out.push('\\'),
1789 b'/' => out.push('/'),
1790 b'b' => out.push('\u{0008}'),
1791 b'f' => out.push('\u{000C}'),
1792 b'n' => out.push('\n'),
1793 b'r' => out.push('\r'),
1794 b't' => out.push('\t'),
1795 b'u' => out.push(self.parse_unicode_escape(escape_index)?),
1796 _ => {
1797 return Err(JsonParseError::InvalidEscape {
1798 index: escape_index,
1799 })
1800 }
1801 }
1802 Ok(())
1803 }
1804
1805 fn parse_unicode_escape(&mut self, index: usize) -> Result<char, JsonParseError> {
1806 let scalar = self.parse_hex_quad(index)?;
1807 if (0xD800..=0xDBFF).contains(&scalar) {
1808 if self.next_byte() != Some(b'\\') || self.next_byte() != Some(b'u') {
1809 return Err(JsonParseError::InvalidUnicodeScalar { index });
1810 }
1811 let low = self.parse_hex_quad(index)?;
1812 if !(0xDC00..=0xDFFF).contains(&low) {
1813 return Err(JsonParseError::InvalidUnicodeScalar { index });
1814 }
1815 let high = scalar - 0xD800;
1816 let low = low - 0xDC00;
1817 let combined = 0x10000 + ((high << 10) | low);
1818 char::from_u32(combined).ok_or(JsonParseError::InvalidUnicodeScalar { index })
1819 } else if (0xDC00..=0xDFFF).contains(&scalar) {
1820 Err(JsonParseError::InvalidUnicodeScalar { index })
1821 } else {
1822 char::from_u32(scalar).ok_or(JsonParseError::InvalidUnicodeScalar { index })
1823 }
1824 }
1825
1826 fn parse_hex_quad(&mut self, index: usize) -> Result<u32, JsonParseError> {
1827 let mut value = 0u32;
1828 for _ in 0..4 {
1829 let ch = self.next_byte().ok_or(JsonParseError::UnexpectedEnd)?;
1830 let digit = match ch {
1831 b'0'..=b'9' => (ch - b'0') as u32,
1832 b'a'..=b'f' => 10 + (ch - b'a') as u32,
1833 b'A'..=b'F' => 10 + (ch - b'A') as u32,
1834 _ => return Err(JsonParseError::InvalidUnicodeEscape { index }),
1835 };
1836 value = (value << 4) | digit;
1837 }
1838 Ok(value)
1839 }
1840
1841 fn parse_number(&mut self) -> Result<JsonNumber, JsonParseError> {
1842 let start = self.index;
1843 self.try_consume_byte(b'-');
1844 if self.try_consume_byte(b'0') {
1845 if matches!(self.peek_byte(), Some(b'0'..=b'9')) {
1846 return Err(JsonParseError::InvalidNumber { index: start });
1847 }
1848 } else {
1849 self.consume_digits(start)?;
1850 }
1851
1852 let mut is_float = false;
1853 if self.try_consume_byte(b'.') {
1854 is_float = true;
1855 self.consume_digits(start)?;
1856 }
1857 if matches!(self.peek_byte(), Some(b'e' | b'E')) {
1858 is_float = true;
1859 self.index += 1;
1860 if matches!(self.peek_byte(), Some(b'+' | b'-')) {
1861 self.index += 1;
1862 }
1863 self.consume_digits(start)?;
1864 }
1865
1866 let token = &self.input[start..self.index];
1867 if is_float {
1868 let value = token
1869 .parse::<f64>()
1870 .map_err(|_| JsonParseError::InvalidNumber { index: start })?;
1871 if !value.is_finite() {
1872 return Err(JsonParseError::InvalidNumber { index: start });
1873 }
1874 Ok(JsonNumber::F64(value))
1875 } else if token.starts_with('-') {
1876 let value = token
1877 .parse::<i64>()
1878 .map_err(|_| JsonParseError::InvalidNumber { index: start })?;
1879 Ok(JsonNumber::I64(value))
1880 } else {
1881 let value = token
1882 .parse::<u64>()
1883 .map_err(|_| JsonParseError::InvalidNumber { index: start })?;
1884 Ok(JsonNumber::U64(value))
1885 }
1886 }
1887
1888 fn parse_tape_number(
1889 &mut self,
1890 tokens: &mut Vec<TapeToken>,
1891 parent: Option<usize>,
1892 ) -> Result<usize, JsonParseError> {
1893 let start = self.index;
1894 let _ = self.parse_number()?;
1895 let token_index = tokens.len();
1896 tokens.push(TapeToken {
1897 kind: TapeTokenKind::Number,
1898 start,
1899 end: self.index,
1900 parent,
1901 });
1902 Ok(token_index)
1903 }
1904
1905 fn consume_digits(&mut self, index: usize) -> Result<(), JsonParseError> {
1906 let start = self.index;
1907 while matches!(self.peek_byte(), Some(b'0'..=b'9')) {
1908 self.index += 1;
1909 }
1910 if self.index == start {
1911 return Err(JsonParseError::InvalidNumber { index });
1912 }
1913 Ok(())
1914 }
1915
1916 fn consume_byte(&mut self, expected: u8) -> Result<(), JsonParseError> {
1917 match self.next_byte() {
1918 Some(found) if found == expected => Ok(()),
1919 Some(found) => Err(JsonParseError::UnexpectedCharacter {
1920 index: self.index.saturating_sub(1),
1921 found: found as char,
1922 }),
1923 None => Err(JsonParseError::UnexpectedEnd),
1924 }
1925 }
1926
1927 fn try_consume_byte(&mut self, expected: u8) -> bool {
1928 if self.peek_byte() == Some(expected) {
1929 self.index += 1;
1930 true
1931 } else {
1932 false
1933 }
1934 }
1935
1936 fn skip_whitespace(&mut self) {
1937 while matches!(self.peek_byte(), Some(b' ' | b'\n' | b'\r' | b'\t')) {
1938 self.index += 1;
1939 }
1940 }
1941
1942 fn peek_byte(&self) -> Option<u8> {
1943 self.bytes.get(self.index).copied()
1944 }
1945
1946 fn next_byte(&mut self) -> Option<u8> {
1947 let byte = self.peek_byte()?;
1948 self.index += 1;
1949 Some(byte)
1950 }
1951
1952 fn is_eof(&self) -> bool {
1953 self.index >= self.input.len()
1954 }
1955}
1956
1957#[cfg(test)]
1958mod tests {
1959 use super::*;
1960
1961 #[test]
1962 fn escapes_control_characters_and_quotes() {
1963 let escaped = escape_json_string("hello\t\"world\"\n\u{0007}");
1964 assert_eq!(escaped, "\"hello\\t\\\"world\\\"\\n\\u0007\"");
1965 }
1966
1967 #[test]
1968 fn serializes_nested_values() {
1969 let value = JsonValue::object(vec![
1970 ("name", "node-1".into()),
1971 ("ok", true.into()),
1972 (
1973 "values",
1974 JsonValue::array(vec![1u32.into(), 2u32.into(), JsonValue::Null]),
1975 ),
1976 ]);
1977 assert_eq!(
1978 value.to_json_string().unwrap(),
1979 "{\"name\":\"node-1\",\"ok\":true,\"values\":[1,2,null]}"
1980 );
1981 }
1982
1983 #[test]
1984 fn rejects_non_finite_float() {
1985 let value = JsonValue::from(f64::NAN);
1986 assert_eq!(value.to_json_string(), Err(JsonError::NonFiniteNumber));
1987 }
1988
1989 #[test]
1990 fn parses_basic_json_values() {
1991 assert_eq!(parse_json("null").unwrap(), JsonValue::Null);
1992 assert_eq!(parse_json("true").unwrap(), JsonValue::Bool(true));
1993 assert_eq!(
1994 parse_json("\"hello\"").unwrap(),
1995 JsonValue::String("hello".into())
1996 );
1997 assert_eq!(
1998 parse_json("123").unwrap(),
1999 JsonValue::Number(JsonNumber::U64(123))
2000 );
2001 assert_eq!(
2002 parse_json("-123").unwrap(),
2003 JsonValue::Number(JsonNumber::I64(-123))
2004 );
2005 }
2006
2007 #[test]
2008 fn parses_unicode_and_escapes() {
2009 let value = parse_json("\"line\\n\\u03bb\\uD83D\\uDE80\"").unwrap();
2010 assert_eq!(value, JsonValue::String("line\nλ🚀".into()));
2011 }
2012
2013 #[test]
2014 fn borrowed_parse_avoids_allocating_plain_strings() {
2015 let value = parse_json_borrowed("{\"name\":\"hello\",\"n\":1}").unwrap();
2016 match value {
2017 BorrowedJsonValue::Object(entries) => {
2018 assert!(matches!(entries[0].0, Cow::Borrowed(_)));
2019 assert!(matches!(
2020 entries[0].1,
2021 BorrowedJsonValue::String(Cow::Borrowed(_))
2022 ));
2023 }
2024 other => panic!("unexpected value: {other:?}"),
2025 }
2026 }
2027
2028 #[test]
2029 fn borrowed_parse_allocates_when_unescaping_is_needed() {
2030 let value = parse_json_borrowed("\"line\\nvalue\"").unwrap();
2031 match value {
2032 BorrowedJsonValue::String(Cow::Owned(text)) => assert_eq!(text, "line\nvalue"),
2033 other => panic!("unexpected value: {other:?}"),
2034 }
2035 }
2036
2037 #[test]
2038 fn compiled_schema_serializes_expected_shape() {
2039 let schema = CompiledObjectSchema::new(&["id", "name", "enabled"]);
2040 let values = [
2041 JsonValue::from(7u64),
2042 JsonValue::from("node-7"),
2043 JsonValue::from(true),
2044 ];
2045 let json = schema.to_json_string(values.iter()).unwrap();
2046 assert_eq!(json, "{\"id\":7,\"name\":\"node-7\",\"enabled\":true}");
2047 }
2048
2049 #[test]
2050 fn compiled_row_schema_serializes_array_of_objects() {
2051 let schema = CompiledRowSchema::new(&["id", "name"]);
2052 let row1 = [JsonValue::from(1u64), JsonValue::from("a")];
2053 let row2 = [JsonValue::from(2u64), JsonValue::from("b")];
2054 let json = schema.to_json_string([row1.iter(), row2.iter()]).unwrap();
2055 assert_eq!(json, r#"[{"id":1,"name":"a"},{"id":2,"name":"b"}]"#);
2056 }
2057
2058 #[test]
2059 fn tape_parse_records_structure_tokens() {
2060 let tape = parse_json_tape(r#"{"a":[1,"x"],"b":true}"#).unwrap();
2061 assert_eq!(tape.tokens[0].kind, TapeTokenKind::Object);
2062 assert_eq!(tape.tokens[1].kind, TapeTokenKind::Key);
2063 assert_eq!(tape.tokens[2].kind, TapeTokenKind::Array);
2064 assert_eq!(tape.tokens[3].kind, TapeTokenKind::Number);
2065 assert_eq!(tape.tokens[4].kind, TapeTokenKind::String);
2066 assert_eq!(tape.tokens[5].kind, TapeTokenKind::Key);
2067 assert_eq!(tape.tokens[6].kind, TapeTokenKind::Bool);
2068 }
2069
2070 #[test]
2071 fn tape_object_lookup_finds_child_values() {
2072 let input = r#"{"name":"hello","nested":{"x":1},"flag":true}"#;
2073 let tape = parse_json_tape(input).unwrap();
2074 let root = tape.root(input).unwrap();
2075 let name = root.get("name").unwrap();
2076 assert_eq!(name.kind(), TapeTokenKind::String);
2077 assert_eq!(name.as_str(), Some("hello"));
2078 let nested = root.get("nested").unwrap();
2079 assert_eq!(nested.kind(), TapeTokenKind::Object);
2080 assert!(root.get("missing").is_none());
2081 }
2082
2083 #[test]
2084 fn tape_object_index_lookup_finds_child_values() {
2085 let input = r#"{"name":"hello","nested":{"x":1},"flag":true}"#;
2086 let tape = parse_json_tape(input).unwrap();
2087 let root = tape.root(input).unwrap();
2088 let index = root.build_object_index().unwrap();
2089 let flag = index.get(root, "flag").unwrap();
2090 assert_eq!(flag.kind(), TapeTokenKind::Bool);
2091 assert!(index.get(root, "missing").is_none());
2092 }
2093
2094 #[test]
2095 fn indexed_tape_object_compiled_lookup_finds_child_values() {
2096 let input = r#"{"name":"hello","nested":{"x":1},"flag":true}"#;
2097 let tape = parse_json_tape(input).unwrap();
2098 let root = tape.root(input).unwrap();
2099 let index = root.build_object_index().unwrap();
2100 let indexed = root.with_index(&index);
2101 let keys = CompiledTapeKeys::new(&["name", "flag", "missing"]);
2102 let got = indexed
2103 .get_compiled_many(&keys)
2104 .map(|value| value.map(|value| value.kind()))
2105 .collect::<Vec<_>>();
2106 assert_eq!(got, vec![Some(TapeTokenKind::String), Some(TapeTokenKind::Bool), None]);
2107 }
2108
2109 #[test]
2110 fn serde_style_convenience_api_works() {
2111 let value = from_str(r#"{"ok":true,"n":7,"items":[1,2,3],"msg":"hello"}"#).unwrap();
2112 assert!(value.is_object());
2113 assert_eq!(value["ok"].as_bool(), Some(true));
2114 assert_eq!(value["n"].as_i64(), Some(7));
2115 assert_eq!(value["msg"].as_str(), Some("hello"));
2116 assert_eq!(value["items"][1].as_u64(), Some(2));
2117 assert!(value["missing"].is_null());
2118 assert_eq!(to_string(&value).unwrap(), r#"{"ok":true,"n":7,"items":[1,2,3],"msg":"hello"}"#);
2119 assert_eq!(from_slice(br#"[1,true,"x"]"#).unwrap()[2].as_str(), Some("x"));
2120 assert_eq!(to_vec(&value).unwrap(), value.to_json_string().unwrap().into_bytes());
2121 }
2122
2123 #[test]
2124 fn json_macro_builds_values() {
2125 let value = json!({"ok": true, "items": [1, 2, null], "msg": "x"});
2126 assert_eq!(value["ok"].as_bool(), Some(true));
2127 assert_eq!(value["items"][0].as_u64(), Some(1));
2128 assert!(value["items"][2].is_null());
2129 assert_eq!(value["msg"].as_str(), Some("x"));
2130 }
2131
2132 #[test]
2133 fn from_slice_rejects_invalid_utf8() {
2134 assert!(matches!(from_slice(&[0xff]), Err(JsonParseError::InvalidUtf8)));
2135 }
2136
2137 #[test]
2138 fn reader_writer_and_collection_helpers_work() {
2139 let value = from_reader(std::io::Cursor::new(br#"{"a":1,"b":[true,false]}"# as &[u8])).unwrap();
2140 assert_eq!(value["a"].as_u64(), Some(1));
2141 assert_eq!(value["b"].len(), 2);
2142 assert_eq!(value["b"].get_index(1).and_then(JsonValue::as_bool), Some(false));
2143
2144 let mut out = Vec::new();
2145 to_writer(&mut out, &value).unwrap();
2146 assert_eq!(String::from_utf8(out).unwrap(), value.to_json_string().unwrap());
2147
2148 let object = JsonValue::from_iter([("x", 1u64), ("y", 2u64)]);
2149 assert_eq!(object["x"].as_u64(), Some(1));
2150 let array = JsonValue::from_iter([1u64, 2u64, 3u64]);
2151 assert_eq!(array.get_index(2).and_then(JsonValue::as_u64), Some(3));
2152 }
2153
2154 #[test]
2155 fn rejects_invalid_json_inputs() {
2156 assert!(matches!(
2157 parse_json("{"),
2158 Err(JsonParseError::UnexpectedEnd)
2159 ));
2160 assert!(matches!(
2161 parse_json("{\"a\" 1}"),
2162 Err(JsonParseError::ExpectedColon { .. })
2163 ));
2164 assert!(matches!(
2165 parse_json("[1 2]"),
2166 Err(JsonParseError::ExpectedCommaOrEnd {
2167 context: "array",
2168 ..
2169 })
2170 ));
2171 assert!(matches!(
2172 parse_json("{\"a\":1 trailing"),
2173 Err(JsonParseError::ExpectedCommaOrEnd {
2174 context: "object",
2175 ..
2176 })
2177 ));
2178 assert!(matches!(
2179 parse_json("00"),
2180 Err(JsonParseError::InvalidNumber { .. })
2181 ));
2182 }
2183
2184 #[test]
2185 fn roundtrips_specific_structures() {
2186 let values = [
2187 JsonValue::Null,
2188 JsonValue::Bool(false),
2189 JsonValue::String("tab\tquote\"slash\\snowman☃".into()),
2190 JsonValue::Number(JsonNumber::I64(-9_223_372_036_854_775_808)),
2191 JsonValue::Number(JsonNumber::U64(u64::MAX)),
2192 JsonValue::Number(JsonNumber::F64(12345.125)),
2193 JsonValue::Array(vec![
2194 JsonValue::Bool(true),
2195 JsonValue::String("nested".into()),
2196 JsonValue::Object(vec![("x".into(), 1u64.into())]),
2197 ]),
2198 ];
2199 for value in values {
2200 let text = value.to_json_string().unwrap();
2201 let reparsed = parse_json(&text).unwrap();
2202 assert_json_equivalent(&value, &reparsed);
2203 }
2204 }
2205
2206 #[test]
2207 fn deterministic_fuzz_roundtrip_strings_and_values() {
2208 let mut rng = Rng::new(0x5eed_1234_5678_9abc);
2209 for _ in 0..2_000 {
2210 let input = random_string(&mut rng, 48);
2211 let escaped = escape_json_string(&input);
2212 let parsed = parse_json(&escaped).unwrap();
2213 assert_eq!(parsed, JsonValue::String(input));
2214 }
2215
2216 for _ in 0..1_000 {
2217 let value = random_json_value(&mut rng, 0, 4);
2218 let text = value.to_json_string().unwrap();
2219 let reparsed = parse_json(&text).unwrap();
2220 assert_json_equivalent(&value, &reparsed);
2221 }
2222 }
2223
2224 fn assert_json_equivalent(expected: &JsonValue, actual: &JsonValue) {
2225 match (expected, actual) {
2226 (JsonValue::Null, JsonValue::Null) => {}
2227 (JsonValue::Bool(a), JsonValue::Bool(b)) => assert_eq!(a, b),
2228 (JsonValue::String(a), JsonValue::String(b)) => assert_eq!(a, b),
2229 (JsonValue::Number(a), JsonValue::Number(b)) => assert_numbers_equivalent(a, b),
2230 (JsonValue::Array(a), JsonValue::Array(b)) => {
2231 assert_eq!(a.len(), b.len());
2232 for (left, right) in a.iter().zip(b.iter()) {
2233 assert_json_equivalent(left, right);
2234 }
2235 }
2236 (JsonValue::Object(a), JsonValue::Object(b)) => {
2237 assert_eq!(a.len(), b.len());
2238 for ((left_key, left_value), (right_key, right_value)) in a.iter().zip(b.iter()) {
2239 assert_eq!(left_key, right_key);
2240 assert_json_equivalent(left_value, right_value);
2241 }
2242 }
2243 _ => panic!("json values differ: expected {expected:?}, actual {actual:?}"),
2244 }
2245 }
2246
2247 fn assert_numbers_equivalent(expected: &JsonNumber, actual: &JsonNumber) {
2248 match (expected, actual) {
2249 (JsonNumber::I64(a), JsonNumber::I64(b)) => assert_eq!(a, b),
2250 (JsonNumber::U64(a), JsonNumber::U64(b)) => assert_eq!(a, b),
2251 (JsonNumber::F64(a), JsonNumber::F64(b)) => assert_eq!(a.to_bits(), b.to_bits()),
2252 (JsonNumber::I64(a), JsonNumber::U64(b)) if *a >= 0 => assert_eq!(*a as u64, *b),
2253 (JsonNumber::U64(a), JsonNumber::I64(b)) if *b >= 0 => assert_eq!(*a, *b as u64),
2254 (JsonNumber::I64(a), JsonNumber::F64(b)) => assert_eq!(*a as f64, *b),
2255 (JsonNumber::U64(a), JsonNumber::F64(b)) => assert_eq!(*a as f64, *b),
2256 (JsonNumber::F64(a), JsonNumber::I64(b)) => assert_eq!(*a, *b as f64),
2257 (JsonNumber::F64(a), JsonNumber::U64(b)) => assert_eq!(*a, *b as f64),
2258 (left, right) => panic!("json numbers differ: expected {left:?}, actual {right:?}"),
2259 }
2260 }
2261
2262 #[derive(Clone, Debug)]
2263 struct Rng {
2264 state: u64,
2265 }
2266
2267 impl Rng {
2268 fn new(seed: u64) -> Self {
2269 Self { state: seed }
2270 }
2271
2272 fn next_u64(&mut self) -> u64 {
2273 self.state = self
2274 .state
2275 .wrapping_mul(6364136223846793005)
2276 .wrapping_add(1442695040888963407);
2277 self.state
2278 }
2279
2280 fn choose(&mut self, upper_exclusive: usize) -> usize {
2281 (self.next_u64() % upper_exclusive as u64) as usize
2282 }
2283
2284 fn bool(&mut self) -> bool {
2285 (self.next_u64() & 1) == 1
2286 }
2287 }
2288
2289 fn random_string(rng: &mut Rng, max_len: usize) -> String {
2290 let len = rng.choose(max_len + 1);
2291 let mut out = String::new();
2292 for _ in 0..len {
2293 let ch = match rng.choose(12) {
2294 0 => '"',
2295 1 => '\\',
2296 2 => '\n',
2297 3 => '\r',
2298 4 => '\t',
2299 5 => '\u{0007}',
2300 6 => 'λ',
2301 7 => '🚀',
2302 8 => '☃',
2303 _ => (b'a' + rng.choose(26) as u8) as char,
2304 };
2305 out.push(ch);
2306 }
2307 out
2308 }
2309
2310 fn random_json_value(rng: &mut Rng, depth: usize, max_depth: usize) -> JsonValue {
2311 if depth >= max_depth {
2312 return random_leaf(rng);
2313 }
2314 match rng.choose(7) {
2315 0 | 1 | 2 | 3 => random_leaf(rng),
2316 4 => {
2317 let len = rng.choose(5);
2318 let mut values = Vec::with_capacity(len);
2319 for _ in 0..len {
2320 values.push(random_json_value(rng, depth + 1, max_depth));
2321 }
2322 JsonValue::Array(values)
2323 }
2324 _ => {
2325 let len = rng.choose(5);
2326 let mut entries = Vec::with_capacity(len);
2327 for index in 0..len {
2328 entries.push((
2329 format!("k{depth}_{index}_{}", random_string(rng, 6)),
2330 random_json_value(rng, depth + 1, max_depth),
2331 ));
2332 }
2333 JsonValue::Object(entries)
2334 }
2335 }
2336 }
2337
2338 fn random_leaf(rng: &mut Rng) -> JsonValue {
2339 match rng.choose(6) {
2340 0 => JsonValue::Null,
2341 1 => JsonValue::Bool(rng.bool()),
2342 2 => JsonValue::String(random_string(rng, 24)),
2343 3 => JsonValue::Number(JsonNumber::I64(
2344 (rng.next_u64() >> 1) as i64 * if rng.bool() { 1 } else { -1 },
2345 )),
2346 4 => JsonValue::Number(JsonNumber::U64(rng.next_u64())),
2347 _ => {
2348 let mantissa = (rng.next_u64() % 1_000_000) as f64 / 1000.0;
2349 let sign = if rng.bool() { 1.0 } else { -1.0 };
2350 JsonValue::Number(JsonNumber::F64(sign * mantissa))
2351 }
2352 }
2353 }
2354}