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}