Skip to main content

lifegraph_json/
lib.rs

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}