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