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