Skip to main content

lifegraph_json/
lib.rs

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