Skip to main content

lifegraph_json/
lib.rs

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