1use core::{char, str};
2
3const MAX_DEPTH: usize = 64;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
6pub struct JsonString<'a> {
7 encoded: &'a str,
8 escaped: bool,
9}
10
11impl<'a> JsonString<'a> {
12 pub const fn encoded(&self) -> &'a str {
13 self.encoded
14 }
15
16 pub fn as_str(&self) -> Option<&'a str> {
17 (!self.escaped).then_some(self.encoded)
18 }
19
20 pub fn decode_into<'buffer>(
21 &self,
22 buffer: &'buffer mut [u8],
23 ) -> Result<&'buffer str, JsonError> {
24 if !self.escaped {
25 let destination = buffer
26 .get_mut(..self.encoded.len())
27 .ok_or(JsonError::BufferTooSmall)?;
28 destination.copy_from_slice(self.encoded.as_bytes());
29 return str::from_utf8(destination).map_err(|_| JsonError::InvalidUtf8);
30 }
31
32 let mut output = 0;
33 for character in self.decoded_chars() {
34 let mut encoded = [0; 4];
35 copy_decoded(
36 buffer,
37 &mut output,
38 character?.encode_utf8(&mut encoded).as_bytes(),
39 )?;
40 }
41 str::from_utf8(&buffer[..output]).map_err(|_| JsonError::InvalidUtf8)
42 }
43
44 pub(crate) fn decoded_eq_ascii(&self, expected: &str) -> bool {
45 if !expected.is_ascii() {
46 return false;
47 }
48 if !self.escaped {
49 return self.encoded == expected;
50 }
51 self.decoded_chars().eq(expected.chars().map(Ok))
52 }
53
54 fn decoded_chars(&self) -> impl Iterator<Item = Result<char, JsonError>> + '_ {
55 let mut source = self.encoded;
56 core::iter::from_fn(move || {
57 let first = source.chars().next()?;
58 let result = if first == '\\' {
59 escaped_character(source.as_bytes(), 0)
60 } else {
61 Ok((first, first.len_utf8()))
62 };
63 source = match result {
64 Ok((_, length)) => &source[length..],
65 Err(_) => "",
66 };
67 Some(result.map(|(character, _)| character))
68 })
69 }
70}
71
72#[derive(Clone, Copy, Debug, Eq, PartialEq, derive_more::Display)]
73pub enum JsonError {
74 #[display("JSON is not UTF-8")]
75 InvalidUtf8,
76 #[display("invalid JSON syntax")]
77 InvalidSyntax,
78 #[display("JSON nesting is too deep")]
79 NestingTooDeep,
80 #[display("invalid JSON string escape")]
81 InvalidEscape,
82 #[display("invalid JSON number")]
83 InvalidNumber,
84 #[display("unexpected JSON value type")]
85 WrongType,
86 #[display("missing JSON field {_0}")]
87 MissingField(&'static str),
88 #[display("duplicate JSON field {_0}")]
89 DuplicateField(&'static str),
90 #[display("JSON string output buffer is too small")]
91 BufferTooSmall,
92}
93
94#[derive(Clone, Copy, Debug, Eq, PartialEq)]
95pub(crate) struct Value<'a> {
96 bytes: &'a [u8],
97}
98
99impl<'a> Value<'a> {
100 pub(crate) fn parse_document(bytes: &'a [u8]) -> Result<Self, JsonError> {
101 str::from_utf8(bytes).map_err(|_| JsonError::InvalidUtf8)?;
102 let start = whitespace(bytes, 0);
103 let end = parse_value(bytes, start, 0)?;
104 if whitespace(bytes, end) != bytes.len() {
105 return Err(JsonError::InvalidSyntax);
106 }
107 Ok(Self {
108 bytes: &bytes[start..end],
109 })
110 }
111
112 pub(crate) fn object(self) -> Result<Object<'a>, JsonError> {
113 if self.bytes.first() != Some(&b'{') {
114 return Err(JsonError::WrongType);
115 }
116 Ok(Object { bytes: self.bytes })
117 }
118
119 pub(crate) fn array(self) -> Result<Array<'a>, JsonError> {
120 if self.bytes.first() != Some(&b'[') {
121 return Err(JsonError::WrongType);
122 }
123 Ok(Array { bytes: self.bytes })
124 }
125
126 pub(crate) fn string(self) -> Result<JsonString<'a>, JsonError> {
127 if self.bytes.first() != Some(&b'"') || self.bytes.last() != Some(&b'"') {
128 return Err(JsonError::WrongType);
129 }
130 let encoded = str::from_utf8(&self.bytes[1..self.bytes.len() - 1])
131 .map_err(|_| JsonError::InvalidUtf8)?;
132 Ok(JsonString {
133 encoded,
134 escaped: encoded.as_bytes().contains(&b'\\'),
135 })
136 }
137
138 pub(crate) fn u64(self) -> Result<u64, JsonError> {
139 let value = str::from_utf8(self.bytes).map_err(|_| JsonError::InvalidUtf8)?;
140 if value.is_empty() || !value.bytes().all(|byte| byte.is_ascii_digit()) {
141 return Err(JsonError::WrongType);
142 }
143 value.parse().map_err(|_| JsonError::InvalidNumber)
144 }
145
146 pub(crate) fn is_null(self) -> bool {
147 self.bytes == b"null"
148 }
149}
150
151#[derive(Clone, Copy, Debug, Eq, PartialEq)]
152pub(crate) struct Object<'a> {
153 bytes: &'a [u8],
154}
155
156impl<'a> Object<'a> {
157 pub(crate) fn get(self, name: &'static str) -> Result<Option<Value<'a>>, JsonError> {
158 let mut found = None;
159 for member in self.iter() {
160 let (key, value) = member?;
161 if key.decoded_eq_ascii(name) {
162 if found.is_some() {
163 return Err(JsonError::DuplicateField(name));
164 }
165 found = Some(value);
166 }
167 }
168 Ok(found)
169 }
170
171 pub(crate) fn required(self, name: &'static str) -> Result<Value<'a>, JsonError> {
172 self.get(name)?.ok_or(JsonError::MissingField(name))
173 }
174
175 pub(crate) fn iter(self) -> ObjectIter<'a> {
176 ObjectIter(Container::new(self.bytes, 0, b'}'))
177 }
178}
179
180pub(crate) struct ObjectIter<'a>(Container<'a>);
181
182impl<'a> Iterator for ObjectIter<'a> {
183 type Item = Result<(JsonString<'a>, Value<'a>), JsonError>;
184
185 fn next(&mut self) -> Option<Self::Item> {
186 self.0.next(0).map(|member| {
187 let (key, value) = member?;
188 Ok((key.expect("object member has a key"), value))
189 })
190 }
191}
192
193#[derive(Clone, Copy, Debug, Eq, PartialEq)]
194pub(crate) struct Array<'a> {
195 bytes: &'a [u8],
196}
197
198impl<'a> Array<'a> {
199 pub(crate) fn iter(self) -> ArrayIter<'a> {
200 ArrayIter(Container::new(self.bytes, 0, b']'))
201 }
202}
203
204pub(crate) struct ArrayIter<'a>(Container<'a>);
205
206impl<'a> Iterator for ArrayIter<'a> {
207 type Item = Result<Value<'a>, JsonError>;
208
209 fn next(&mut self) -> Option<Self::Item> {
210 self.0.next(0).map(|member| member.map(|(_, value)| value))
211 }
212}
213
214struct Container<'a> {
216 bytes: &'a [u8],
217 closing: u8,
218 first: bool,
219 finished: bool,
220}
221
222type Member<'a> = (Option<JsonString<'a>>, Value<'a>);
223
224impl<'a> Container<'a> {
225 fn new(bytes: &'a [u8], opening: usize, closing: u8) -> Self {
226 Self {
227 bytes: &bytes[opening + 1..],
228 closing,
229 first: true,
230 finished: false,
231 }
232 }
233
234 fn next(&mut self, depth: usize) -> Option<Result<Member<'a>, JsonError>> {
235 if self.finished {
236 return None;
237 }
238 let result = self.next_inner(depth);
239 if result.is_err() {
240 self.finished = true;
241 }
242 result.transpose()
243 }
244
245 fn next_inner(&mut self, depth: usize) -> Result<Option<Member<'a>>, JsonError> {
246 self.bytes = &self.bytes[whitespace(self.bytes, 0)..];
247 if self.bytes.first() == Some(&self.closing) {
248 self.bytes = &self.bytes[1..];
249 self.finished = true;
250 return Ok(None);
251 }
252 if !self.first {
253 if self.bytes.first() != Some(&b',') {
254 return Err(JsonError::InvalidSyntax);
255 }
256 self.bytes = &self.bytes[whitespace(self.bytes, 1)..];
257 }
258 self.first = false;
259 let key = if self.closing == b'}' {
260 if self.bytes.first() != Some(&b'"') {
261 return Err(JsonError::InvalidSyntax);
262 }
263 let end = parse_string(self.bytes, 0)?;
264 let key = Value {
265 bytes: &self.bytes[..end],
266 }
267 .string()?;
268 self.bytes = &self.bytes[whitespace(self.bytes, end)..];
269 if self.bytes.first() != Some(&b':') {
270 return Err(JsonError::InvalidSyntax);
271 }
272 self.bytes = &self.bytes[whitespace(self.bytes, 1)..];
273 Some(key)
274 } else {
275 None
276 };
277 let end = parse_value(self.bytes, 0, depth)?;
278 let value = Value {
279 bytes: &self.bytes[..end],
280 };
281 self.bytes = &self.bytes[end..];
282 Ok(Some((key, value)))
283 }
284}
285
286fn parse_value(bytes: &[u8], position: usize, depth: usize) -> Result<usize, JsonError> {
287 if depth > MAX_DEPTH {
288 return Err(JsonError::NestingTooDeep);
289 }
290 match bytes.get(position).copied() {
291 Some(b'"') => parse_string(bytes, position),
292 Some(b'{') => parse_container(bytes, position, b'}', depth + 1),
293 Some(b'[') => parse_container(bytes, position, b']', depth + 1),
294 Some(b't') => literal(bytes, position, b"true"),
295 Some(b'f') => literal(bytes, position, b"false"),
296 Some(b'n') => literal(bytes, position, b"null"),
297 Some(b'-' | b'0'..=b'9') => parse_number(bytes, position),
298 _ => Err(JsonError::InvalidSyntax),
299 }
300}
301
302fn parse_container(
303 bytes: &[u8],
304 position: usize,
305 closing: u8,
306 depth: usize,
307) -> Result<usize, JsonError> {
308 let mut container = Container::new(bytes, position, closing);
309 while let Some(member) = container.next(depth) {
310 member?;
311 }
312 Ok(bytes.len() - container.bytes.len())
313}
314
315fn parse_string(bytes: &[u8], position: usize) -> Result<usize, JsonError> {
316 let mut index = position + 1;
317 while let Some(byte) = bytes.get(index).copied() {
318 match byte {
319 b'"' => return Ok(index + 1),
320 b'\\' => {
321 let (_, next) = escaped_character(bytes, index)?;
322 index = next;
323 }
324 0..=0x1f => return Err(JsonError::InvalidSyntax),
325 _ => index += 1,
326 }
327 }
328 Err(JsonError::InvalidSyntax)
329}
330
331fn escaped_character(bytes: &[u8], slash: usize) -> Result<(char, usize), JsonError> {
332 let character = match bytes.get(slash + 1).copied() {
333 Some(value @ (b'"' | b'\\' | b'/')) => char::from(value),
334 Some(b'b') => '\u{0008}',
335 Some(b'f') => '\u{000c}',
336 Some(b'n') => '\n',
337 Some(b'r') => '\r',
338 Some(b't') => '\t',
339 Some(b'u') => return unicode_character(bytes, slash + 2),
340 _ => return Err(JsonError::InvalidEscape),
341 };
342 Ok((character, slash + 2))
343}
344
345fn unicode_character(bytes: &[u8], start: usize) -> Result<(char, usize), JsonError> {
346 let first = unicode_escape(bytes, start)?;
347 let next = start + 4;
348 let scalar = if (0xd800..=0xdbff).contains(&first) {
349 if bytes.get(next..next + 2) != Some(b"\\u") {
350 return Err(JsonError::InvalidEscape);
351 }
352 let second = unicode_escape(bytes, next + 2)?;
353 if !(0xdc00..=0xdfff).contains(&second) {
354 return Err(JsonError::InvalidEscape);
355 }
356 let high = u32::from(first - 0xd800);
357 let low = u32::from(second - 0xdc00);
358 (0x10000 + (high << 10) + low, next + 6)
359 } else if (0xdc00..=0xdfff).contains(&first) {
360 return Err(JsonError::InvalidEscape);
361 } else {
362 (u32::from(first), next)
363 };
364 let character = char::from_u32(scalar.0).ok_or(JsonError::InvalidEscape)?;
365 Ok((character, scalar.1))
366}
367
368fn unicode_escape(bytes: &[u8], start: usize) -> Result<u16, JsonError> {
369 let digits = bytes
370 .get(start..start + 4)
371 .ok_or(JsonError::InvalidEscape)?;
372 let mut value = 0u16;
373 for digit in digits {
374 value = (value << 4) | u16::from(hex(*digit).ok_or(JsonError::InvalidEscape)?);
376 }
377 Ok(value)
378}
379
380fn hex(byte: u8) -> Option<u8> {
381 match byte {
382 b'0'..=b'9' => Some(byte - b'0'),
383 b'a'..=b'f' => Some(byte - b'a' + 10),
384 b'A'..=b'F' => Some(byte - b'A' + 10),
385 _ => None,
386 }
387}
388
389fn parse_number(bytes: &[u8], mut position: usize) -> Result<usize, JsonError> {
390 if bytes.get(position) == Some(&b'-') {
391 position += 1;
392 }
393 position = match bytes.get(position) {
394 Some(b'0') => position + 1,
395 Some(b'1'..=b'9') => decimal_digits(bytes, position)?,
396 _ => return Err(JsonError::InvalidNumber),
397 };
398 if bytes.get(position) == Some(&b'.') {
399 position = decimal_digits(bytes, position + 1)?;
400 }
401 if matches!(bytes.get(position), Some(b'e' | b'E')) {
402 position += 1;
403 if matches!(bytes.get(position), Some(b'+' | b'-')) {
404 position += 1;
405 }
406 position = decimal_digits(bytes, position)?;
407 }
408 Ok(position)
409}
410
411fn decimal_digits(bytes: &[u8], start: usize) -> Result<usize, JsonError> {
412 let mut position = start;
413 while matches!(bytes.get(position), Some(b'0'..=b'9')) {
414 position += 1;
415 }
416 if position == start {
417 return Err(JsonError::InvalidNumber);
418 }
419 Ok(position)
420}
421
422fn literal(bytes: &[u8], position: usize, literal: &[u8]) -> Result<usize, JsonError> {
423 if bytes.get(position..position + literal.len()) == Some(literal) {
424 Ok(position + literal.len())
425 } else {
426 Err(JsonError::InvalidSyntax)
427 }
428}
429
430fn whitespace(bytes: &[u8], mut position: usize) -> usize {
431 while matches!(bytes.get(position), Some(b' ' | b'\n' | b'\r' | b'\t')) {
432 position += 1;
433 }
434 position
435}
436
437fn copy_decoded(buffer: &mut [u8], output: &mut usize, bytes: &[u8]) -> Result<(), JsonError> {
438 crate::buffer::append(buffer, output, bytes).map_err(|_| JsonError::BufferTooSmall)
439}
440
441#[cfg(test)]
442mod tests {
443 use std::{format, string::ToString};
444
445 use super::{parse_value, JsonError, Value, MAX_DEPTH};
446
447 #[test]
448 fn validates_and_iterates_nested_json() {
449 let value = Value::parse_document(br#" {"a":[1,{"b":true}],"skip":null} "#).unwrap();
450 let object = value.object().unwrap();
451 let array = object.required("a").unwrap().array().unwrap();
452 assert_eq!(array.iter().count(), 2);
453 assert!(object.get("missing").unwrap().is_none());
454 }
455
456 #[test]
457 fn decodes_strings_and_rejects_bad_surrogates() {
458 let value = Value::parse_document(br#""hello\n\u263a\ud83d\ude00""#).unwrap();
459 let string = value.string().unwrap();
460 let mut output = [0; 32];
461 assert_eq!(string.decode_into(&mut output).unwrap(), "hello\n☺😀");
462 assert_eq!(
463 Value::parse_document(br#""\ud83d!""#),
464 Err(JsonError::InvalidEscape)
465 );
466 }
467
468 #[test]
469 fn rejects_trailing_and_duplicate_requested_fields() {
470 assert!(Value::parse_document(b"{} x").is_err());
471 let object = Value::parse_document(br#"{"a":1,"\u0061":2}"#)
472 .unwrap()
473 .object()
474 .unwrap();
475 assert_eq!(object.get("a"), Err(JsonError::DuplicateField("a")));
476 }
477
478 #[test]
479 fn decodes_every_simple_escape_and_uppercase_hex() {
480 let value = Value::parse_document(br#""\"\\\/\b\f\n\r\t\u004A\u00AF""#).unwrap();
481 let string = value.string().unwrap();
482 let mut output = [0; 32];
483 assert_eq!(
484 string.decode_into(&mut output).unwrap().as_bytes(),
485 b"\"\\/\x08\x0c\n\r\tJ\xc2\xaf"
486 );
487
488 let positioned_backslash = Value::parse_document(br#""a\\b""#)
489 .unwrap()
490 .string()
491 .unwrap();
492 assert_eq!(
493 positioned_backslash.decode_into(&mut output).unwrap(),
494 "a\\b"
495 );
496 }
497
498 #[test]
499 fn exposes_unescaped_strings_and_checks_decoded_ascii_exactly() {
500 let plain = Value::parse_document(br#""plain""#)
501 .unwrap()
502 .string()
503 .unwrap();
504 assert_eq!(plain.encoded(), "plain");
505 assert_eq!(plain.as_str(), Some("plain"));
506 assert!(plain.decoded_eq_ascii("plain"));
507 assert!(!plain.decoded_eq_ascii("other"));
508 assert!(!plain.decoded_eq_ascii("£"));
509
510 let escaped = Value::parse_document(br#""\u0062""#)
511 .unwrap()
512 .string()
513 .unwrap();
514 assert_eq!(escaped.as_str(), None);
515 assert!(escaped.decoded_eq_ascii("b"));
516 assert!(!escaped.decoded_eq_ascii("a"));
517 }
518
519 #[test]
520 fn rejects_raw_control_characters_and_small_decode_buffers() {
521 assert_eq!(
522 Value::parse_document(b"\"line\nfeed\""),
523 Err(JsonError::InvalidSyntax)
524 );
525
526 let plain = Value::parse_document(br#""hello""#)
527 .unwrap()
528 .string()
529 .unwrap();
530 assert_eq!(
531 plain.decode_into(&mut [0; 4]),
532 Err(JsonError::BufferTooSmall)
533 );
534 let escaped = Value::parse_document(br#""\u263a""#)
535 .unwrap()
536 .string()
537 .unwrap();
538 assert_eq!(
539 escaped.decode_into(&mut [0; 2]),
540 Err(JsonError::BufferTooSmall)
541 );
542 }
543
544 #[test]
545 fn accepts_empty_containers_and_false_literal() {
546 assert_eq!(
547 Value::parse_document(b"{}")
548 .unwrap()
549 .object()
550 .unwrap()
551 .iter()
552 .count(),
553 0
554 );
555 assert_eq!(
556 Value::parse_document(b"[]")
557 .unwrap()
558 .array()
559 .unwrap()
560 .iter()
561 .count(),
562 0
563 );
564 assert!(Value::parse_document(b"false").is_ok());
565 }
566
567 #[test]
568 fn rejects_malformed_container_members_and_fuses_iterators() {
569 for bytes in [
570 b"[1,]".as_slice(),
571 b"[,1]",
572 b"[1 2]",
573 b"[1",
574 b"{a:1}",
575 b"{\"a\" 1}",
576 b"{\"a\":}",
577 b"{\"a\":1,}",
578 b"{\"a\":1 \"b\":2}",
579 ] {
580 assert_eq!(
581 Value::parse_document(bytes),
582 Err(JsonError::InvalidSyntax),
583 "{bytes:?}"
584 );
585 }
586 let mut array = Value { bytes: b"[1,]" }.array().unwrap().iter();
587 assert_eq!(array.next().unwrap().unwrap().u64(), Ok(1));
588 assert_eq!(array.next(), Some(Err(JsonError::InvalidSyntax)));
589 assert_eq!(array.next(), None);
590 let mut object = Value {
591 bytes: b"{\"a\" 1}",
592 }
593 .object()
594 .unwrap()
595 .iter();
596 assert_eq!(object.next(), Some(Err(JsonError::InvalidSyntax)));
597 assert_eq!(object.next(), None);
598 }
599
600 #[test]
601 fn enforces_nesting_at_the_exact_limit() {
602 assert_eq!(parse_value(b"null", 0, MAX_DEPTH), Ok(4));
603 assert_eq!(
604 parse_value(b"null", 0, MAX_DEPTH + 1),
605 Err(JsonError::NestingTooDeep)
606 );
607 assert_eq!(
608 parse_value(b"null", 0, MAX_DEPTH + 2),
609 Err(JsonError::NestingTooDeep)
610 );
611
612 let arrays_at_limit = format!("{}null{}", "[".repeat(MAX_DEPTH), "]".repeat(MAX_DEPTH));
613 assert!(Value::parse_document(arrays_at_limit.as_bytes()).is_ok());
614 let arrays_too_deep = format!(
615 "{}null{}",
616 "[".repeat(MAX_DEPTH + 1),
617 "]".repeat(MAX_DEPTH + 1)
618 );
619 assert_eq!(
620 Value::parse_document(arrays_too_deep.as_bytes()),
621 Err(JsonError::NestingTooDeep)
622 );
623
624 let objects_at_limit = format!(
625 "{}null{}",
626 "{\"a\":".repeat(MAX_DEPTH),
627 "}".repeat(MAX_DEPTH)
628 );
629 assert!(Value::parse_document(objects_at_limit.as_bytes()).is_ok());
630 let objects_too_deep = format!(
631 "{}null{}",
632 "{\"a\":".repeat(MAX_DEPTH + 1),
633 "}".repeat(MAX_DEPTH + 1)
634 );
635 assert_eq!(
636 Value::parse_document(objects_too_deep.as_bytes()),
637 Err(JsonError::NestingTooDeep)
638 );
639 }
640
641 #[test]
642 fn validates_each_json_number_form() {
643 for number in ["0", "-1", "10", "1.25", "1e2", "1E+2", "1e-2"] {
644 assert!(
645 Value::parse_document(number.as_bytes()).is_ok(),
646 "number={number:?}"
647 );
648 }
649 for number in ["-", "01", "1.", "1e", "1e+", "1e-"] {
650 assert!(
651 Value::parse_document(number.as_bytes()).is_err(),
652 "number={number:?}"
653 );
654 }
655
656 assert_eq!(Value { bytes: b"" }.u64(), Err(JsonError::WrongType));
657 assert_eq!(Value { bytes: b"12x" }.u64(), Err(JsonError::WrongType));
658 assert_eq!(Value { bytes: b"42" }.u64(), Ok(42));
659 assert_eq!(
660 Value {
661 bytes: b"18446744073709551616"
662 }
663 .u64(),
664 Err(JsonError::InvalidNumber)
665 );
666 }
667
668 #[test]
669 fn string_conversion_checks_both_quotes() {
670 assert_eq!(
671 Value { bytes: b"plain\"" }.string(),
672 Err(JsonError::WrongType)
673 );
674 assert_eq!(
675 Value { bytes: b"\"plain" }.string(),
676 Err(JsonError::WrongType)
677 );
678 }
679
680 #[test]
681 fn formats_every_json_error() {
682 let cases = [
683 (JsonError::InvalidUtf8, "JSON is not UTF-8"),
684 (JsonError::InvalidSyntax, "invalid JSON syntax"),
685 (JsonError::NestingTooDeep, "JSON nesting is too deep"),
686 (JsonError::InvalidEscape, "invalid JSON string escape"),
687 (JsonError::InvalidNumber, "invalid JSON number"),
688 (JsonError::WrongType, "unexpected JSON value type"),
689 (JsonError::MissingField("name"), "missing JSON field name"),
690 (
691 JsonError::DuplicateField("name"),
692 "duplicate JSON field name",
693 ),
694 (
695 JsonError::BufferTooSmall,
696 "JSON string output buffer is too small",
697 ),
698 ];
699 for (error, expected) in cases {
700 assert_eq!(error.to_string(), expected);
701 }
702 }
703}