Skip to main content

neco_json/
parse.rs

1use alloc::string::String;
2use alloc::vec::Vec;
3
4use crate::error::{ParseError, ParseErrorKind};
5use crate::value::JsonValue;
6
7const MAX_DEPTH: usize = 128;
8
9struct Parser<'a> {
10    input: &'a [u8],
11    position: usize,
12    depth: usize,
13}
14
15/// Parses a JSON byte slice into a `JsonValue`.
16pub fn parse(input: &[u8]) -> Result<JsonValue, ParseError> {
17    let mut parser = Parser {
18        input,
19        position: 0,
20        depth: 0,
21    };
22    let value = parser.parse_value()?;
23    parser.skip_whitespace();
24    if parser.position < parser.input.len() {
25        return Err(parser.error(ParseErrorKind::TrailingContent));
26    }
27    Ok(value)
28}
29
30impl<'a> Parser<'a> {
31    fn error(&self, kind: ParseErrorKind) -> ParseError {
32        ParseError {
33            kind,
34            position: self.position,
35        }
36    }
37
38    fn error_at(&self, position: usize, kind: ParseErrorKind) -> ParseError {
39        ParseError { kind, position }
40    }
41
42    fn peek(&self) -> Option<u8> {
43        self.input.get(self.position).copied()
44    }
45
46    fn advance(&mut self) -> Option<u8> {
47        let byte = self.input.get(self.position).copied();
48        if byte.is_some() {
49            self.position += 1;
50        }
51        byte
52    }
53
54    fn expect(&mut self, expected: u8) -> Result<(), ParseError> {
55        match self.advance() {
56            Some(b) if b == expected => Ok(()),
57            Some(b) => {
58                Err(self.error_at(self.position - 1, ParseErrorKind::UnexpectedCharacter(b)))
59            }
60            None => Err(self.error(ParseErrorKind::UnexpectedEnd)),
61        }
62    }
63
64    fn skip_whitespace(&mut self) {
65        while let Some(b) = self.peek() {
66            match b {
67                b' ' | b'\t' | b'\n' | b'\r' => {
68                    self.position += 1;
69                }
70                _ => break,
71            }
72        }
73    }
74
75    fn parse_value(&mut self) -> Result<JsonValue, ParseError> {
76        self.skip_whitespace();
77        match self.peek() {
78            Some(b'n') => self.parse_null(),
79            Some(b't') => self.parse_true(),
80            Some(b'f') => self.parse_false(),
81            Some(b'"') => self.parse_string().map(JsonValue::String),
82            Some(b'[') => self.parse_array(),
83            Some(b'{') => self.parse_object(),
84            Some(b'-') | Some(b'0'..=b'9') => self.parse_number(),
85            Some(b) => Err(self.error(ParseErrorKind::UnexpectedCharacter(b))),
86            None => Err(self.error(ParseErrorKind::UnexpectedEnd)),
87        }
88    }
89
90    fn parse_null(&mut self) -> Result<JsonValue, ParseError> {
91        self.expect_literal(b"null")?;
92        Ok(JsonValue::Null)
93    }
94
95    fn parse_true(&mut self) -> Result<JsonValue, ParseError> {
96        self.expect_literal(b"true")?;
97        Ok(JsonValue::Bool(true))
98    }
99
100    fn parse_false(&mut self) -> Result<JsonValue, ParseError> {
101        self.expect_literal(b"false")?;
102        Ok(JsonValue::Bool(false))
103    }
104
105    fn expect_literal(&mut self, literal: &[u8]) -> Result<(), ParseError> {
106        for &expected in literal {
107            match self.advance() {
108                Some(b) if b == expected => {}
109                Some(b) => {
110                    return Err(
111                        self.error_at(self.position - 1, ParseErrorKind::UnexpectedCharacter(b))
112                    )
113                }
114                None => return Err(self.error(ParseErrorKind::UnexpectedEnd)),
115            }
116        }
117        Ok(())
118    }
119
120    fn parse_number(&mut self) -> Result<JsonValue, ParseError> {
121        let start = self.position;
122
123        // optional minus
124        if self.peek() == Some(b'-') {
125            self.position += 1;
126        }
127
128        // integer part
129        match self.peek() {
130            Some(b'0') => {
131                self.position += 1;
132                // Digits after a leading zero are not allowed.
133                // The trailing-content check catches them.
134            }
135            Some(b'1'..=b'9') => {
136                self.position += 1;
137                while let Some(b'0'..=b'9') = self.peek() {
138                    self.position += 1;
139                }
140            }
141            _ => return Err(self.error(ParseErrorKind::InvalidNumber)),
142        }
143
144        // fraction
145        if self.peek() == Some(b'.') {
146            self.position += 1;
147            let frac_start = self.position;
148            while let Some(b'0'..=b'9') = self.peek() {
149                self.position += 1;
150            }
151            if self.position == frac_start {
152                return Err(self.error(ParseErrorKind::InvalidNumber));
153            }
154        }
155
156        // exponent
157        if matches!(self.peek(), Some(b'e') | Some(b'E')) {
158            self.position += 1;
159            if matches!(self.peek(), Some(b'+') | Some(b'-')) {
160                self.position += 1;
161            }
162            let exp_start = self.position;
163            while let Some(b'0'..=b'9') = self.peek() {
164                self.position += 1;
165            }
166            if self.position == exp_start {
167                return Err(self.error(ParseErrorKind::InvalidNumber));
168            }
169        }
170
171        let slice = &self.input[start..self.position];
172        // UTF-8 safe: number literals are ASCII only.
173        let s = core::str::from_utf8(slice).map_err(|_| self.error(ParseErrorKind::InvalidUtf8))?;
174        let value: f64 = s
175            .parse()
176            .map_err(|_| self.error(ParseErrorKind::InvalidNumber))?;
177        Ok(JsonValue::Number(value))
178    }
179
180    fn parse_string(&mut self) -> Result<String, ParseError> {
181        self.expect(b'"')?;
182        let mut buf = String::new();
183        loop {
184            match self.advance() {
185                Some(b'"') => return Ok(buf),
186                Some(b'\\') => {
187                    let ch = self.parse_escape()?;
188                    buf.push(ch);
189                }
190                Some(b) if b < 0x20 => {
191                    return Err(
192                        self.error_at(self.position - 1, ParseErrorKind::UnexpectedCharacter(b))
193                    );
194                }
195                Some(b) => {
196                    let width = utf8_char_width(b);
197                    if width == 0 {
198                        return Err(self.error(ParseErrorKind::InvalidUtf8));
199                    }
200                    if width == 1 {
201                        buf.push(b as char);
202                    } else {
203                        let start = self.position - 1;
204                        let mut bytes = [0_u8; 4];
205                        bytes[0] = b;
206
207                        for slot in bytes.iter_mut().take(width).skip(1) {
208                            *slot = match self.advance() {
209                                Some(cont) => cont,
210                                None => return Err(self.error(ParseErrorKind::InvalidUtf8)),
211                            };
212                        }
213
214                        if !is_valid_utf8_sequence(&bytes[..width]) {
215                            return Err(self.error(ParseErrorKind::InvalidUtf8));
216                        }
217
218                        let s = core::str::from_utf8(&self.input[start..self.position])
219                            .map_err(|_| self.error(ParseErrorKind::InvalidUtf8))?;
220                        buf.push_str(s);
221                    }
222                }
223                None => return Err(self.error(ParseErrorKind::UnexpectedEnd)),
224            }
225        }
226    }
227
228    fn parse_escape(&mut self) -> Result<char, ParseError> {
229        match self.advance() {
230            Some(b'"') => Ok('"'),
231            Some(b'\\') => Ok('\\'),
232            Some(b'/') => Ok('/'),
233            Some(b'b') => Ok('\u{0008}'),
234            Some(b'f') => Ok('\u{000C}'),
235            Some(b'n') => Ok('\n'),
236            Some(b'r') => Ok('\r'),
237            Some(b't') => Ok('\t'),
238            Some(b'u') => self.parse_unicode_escape(),
239            Some(_) => Err(self.error_at(self.position - 1, ParseErrorKind::InvalidEscape)),
240            None => Err(self.error(ParseErrorKind::UnexpectedEnd)),
241        }
242    }
243
244    fn parse_unicode_escape(&mut self) -> Result<char, ParseError> {
245        let cp = self.parse_hex4()?;
246
247        // High surrogate
248        if (0xD800..=0xDBFF).contains(&cp) {
249            // Verify that another \u follows immediately.
250            self.expect(b'\\')
251                .map_err(|_| self.error(ParseErrorKind::InvalidUnicodeEscape))?;
252            self.expect(b'u')
253                .map_err(|_| self.error(ParseErrorKind::InvalidUnicodeEscape))?;
254            let low = self.parse_hex4()?;
255            if !(0xDC00..=0xDFFF).contains(&low) {
256                return Err(self.error(ParseErrorKind::InvalidUnicodeEscape));
257            }
258            let combined = (cp - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000;
259            char::from_u32(combined).ok_or_else(|| self.error(ParseErrorKind::InvalidUnicodeEscape))
260        } else if (0xDC00..=0xDFFF).contains(&cp) {
261            // Lone low surrogate
262            Err(self.error(ParseErrorKind::InvalidUnicodeEscape))
263        } else {
264            char::from_u32(cp).ok_or_else(|| self.error(ParseErrorKind::InvalidUnicodeEscape))
265        }
266    }
267
268    fn parse_hex4(&mut self) -> Result<u32, ParseError> {
269        let mut value: u32 = 0;
270        for _ in 0..4 {
271            let digit = match self.advance() {
272                Some(b @ b'0'..=b'9') => (b - b'0') as u32,
273                Some(b @ b'a'..=b'f') => (b - b'a' + 10) as u32,
274                Some(b @ b'A'..=b'F') => (b - b'A' + 10) as u32,
275                Some(_) => {
276                    return Err(
277                        self.error_at(self.position - 1, ParseErrorKind::InvalidUnicodeEscape)
278                    )
279                }
280                None => return Err(self.error(ParseErrorKind::InvalidUnicodeEscape)),
281            };
282            value = value * 16 + digit;
283        }
284        Ok(value)
285    }
286
287    fn parse_array(&mut self) -> Result<JsonValue, ParseError> {
288        self.expect(b'[')?;
289        self.depth += 1;
290        if self.depth > MAX_DEPTH {
291            return Err(self.error(ParseErrorKind::NestingTooDeep));
292        }
293
294        self.skip_whitespace();
295        if self.peek() == Some(b']') {
296            self.position += 1;
297            self.depth -= 1;
298            return Ok(JsonValue::Array(Vec::new()));
299        }
300
301        let mut items = Vec::new();
302        loop {
303            let value = self.parse_value()?;
304            items.push(value);
305            self.skip_whitespace();
306            match self.peek() {
307                Some(b',') => {
308                    self.position += 1;
309                }
310                Some(b']') => {
311                    self.position += 1;
312                    self.depth -= 1;
313                    return Ok(JsonValue::Array(items));
314                }
315                Some(b) => return Err(self.error(ParseErrorKind::UnexpectedCharacter(b))),
316                None => return Err(self.error(ParseErrorKind::UnexpectedEnd)),
317            }
318        }
319    }
320
321    fn parse_object(&mut self) -> Result<JsonValue, ParseError> {
322        self.expect(b'{')?;
323        self.depth += 1;
324        if self.depth > MAX_DEPTH {
325            return Err(self.error(ParseErrorKind::NestingTooDeep));
326        }
327
328        self.skip_whitespace();
329        if self.peek() == Some(b'}') {
330            self.position += 1;
331            self.depth -= 1;
332            return Ok(JsonValue::Object(Vec::new()));
333        }
334
335        let mut fields = Vec::new();
336        loop {
337            self.skip_whitespace();
338            if self.peek() != Some(b'"') {
339                return Err(match self.peek() {
340                    Some(b) => self.error(ParseErrorKind::UnexpectedCharacter(b)),
341                    None => self.error(ParseErrorKind::UnexpectedEnd),
342                });
343            }
344            let key = self.parse_string()?;
345            self.skip_whitespace();
346            self.expect(b':')?;
347            let value = self.parse_value()?;
348            fields.push((key, value));
349            self.skip_whitespace();
350            match self.peek() {
351                Some(b',') => {
352                    self.position += 1;
353                }
354                Some(b'}') => {
355                    self.position += 1;
356                    self.depth -= 1;
357                    return Ok(JsonValue::Object(fields));
358                }
359                Some(b) => return Err(self.error(ParseErrorKind::UnexpectedCharacter(b))),
360                None => return Err(self.error(ParseErrorKind::UnexpectedEnd)),
361            }
362        }
363    }
364}
365
366/// Returns the UTF-8 character width from the first byte.
367fn utf8_char_width(b: u8) -> usize {
368    if b < 0x80 {
369        1
370    } else if (0xC2..=0xDF).contains(&b) {
371        2
372    } else if (0xE0..=0xEF).contains(&b) {
373        3
374    } else if (0xF0..=0xF4).contains(&b) {
375        4
376    } else {
377        0
378    }
379}
380
381fn is_valid_utf8_sequence(bytes: &[u8]) -> bool {
382    match bytes {
383        [first, second] => (0xC2..=0xDF).contains(first) && is_continuation_byte(*second),
384        [first, second, third] => {
385            (match *first {
386                0xE0 => (0xA0..=0xBF).contains(second),
387                0xE1..=0xEC | 0xEE..=0xEF => is_continuation_byte(*second),
388                0xED => (0x80..=0x9F).contains(second),
389                _ => false,
390            }) && is_continuation_byte(*third)
391        }
392        [first, second, third, fourth] => {
393            (match *first {
394                0xF0 => (0x90..=0xBF).contains(second),
395                0xF1..=0xF3 => is_continuation_byte(*second),
396                0xF4 => (0x80..=0x8F).contains(second),
397                _ => false,
398            }) && is_continuation_byte(*third)
399                && is_continuation_byte(*fourth)
400        }
401        _ => false,
402    }
403}
404
405fn is_continuation_byte(b: u8) -> bool {
406    (0x80..=0xBF).contains(&b)
407}
408
409#[cfg(test)]
410mod tests {
411    use alloc::string::String;
412    use alloc::vec;
413
414    use super::parse;
415    use crate::{JsonValue, ParseErrorKind};
416
417    #[test]
418    fn parses_basic_types() {
419        assert_eq!(parse(b"null"), Ok(JsonValue::Null));
420        assert_eq!(parse(b"true"), Ok(JsonValue::Bool(true)));
421        assert_eq!(parse(b"false"), Ok(JsonValue::Bool(false)));
422        assert_eq!(parse(b"0"), Ok(JsonValue::Number(0.0)));
423        assert_eq!(parse(b"-12"), Ok(JsonValue::Number(-12.0)));
424        assert_eq!(parse(b"3.5"), Ok(JsonValue::Number(3.5)));
425        assert_eq!(parse(b"1.25e2"), Ok(JsonValue::Number(125.0)));
426        assert_eq!(
427            parse(br#""hello""#),
428            Ok(JsonValue::String(String::from("hello")))
429        );
430    }
431
432    #[test]
433    fn parses_string_escapes() {
434        assert_eq!(
435            parse(br#""\"\\\/\b\f\n\r\t""#),
436            Ok(JsonValue::String(String::from(
437                "\"\\/\u{0008}\u{000C}\n\r\t"
438            )))
439        );
440    }
441
442    #[test]
443    fn parses_unicode_escapes_and_surrogate_pairs() {
444        assert_eq!(
445            parse(br#""\u0041""#),
446            Ok(JsonValue::String(String::from("A")))
447        );
448        assert_eq!(
449            parse(br#""\u3042""#),
450            Ok(JsonValue::String(String::from("あ")))
451        );
452        assert_eq!(
453            parse(br#""\uD83D\uDE00""#),
454            Ok(JsonValue::String(String::from("😀")))
455        );
456    }
457
458    #[test]
459    fn parses_nested_values() {
460        assert_eq!(
461            parse(br#"{"items":[{"flag":true},[null,{"n":2}]],"name":"ok"}"#),
462            Ok(JsonValue::Object(vec![
463                (
464                    String::from("items"),
465                    JsonValue::Array(vec![
466                        JsonValue::Object(vec![(String::from("flag"), JsonValue::Bool(true))]),
467                        JsonValue::Array(vec![
468                            JsonValue::Null,
469                            JsonValue::Object(vec![(String::from("n"), JsonValue::Number(2.0))]),
470                        ]),
471                    ]),
472                ),
473                (String::from("name"), JsonValue::String(String::from("ok"))),
474            ]))
475        );
476    }
477
478    #[test]
479    fn parses_deep_nesting_at_limit() {
480        let mut input = vec![b'['; 128];
481        input.extend(vec![b']'; 128]);
482        // The innermost value is an empty array. 128 levels is allowed.
483        assert!(parse(&input).is_ok());
484    }
485
486    #[test]
487    fn skips_whitespace() {
488        assert_eq!(
489            parse(b" \n\t\r {\"a\" : [ true , null ] } \n"),
490            Ok(JsonValue::Object(vec![(
491                String::from("a"),
492                JsonValue::Array(vec![JsonValue::Bool(true), JsonValue::Null]),
493            )]))
494        );
495    }
496
497    #[test]
498    fn reports_trailing_content() {
499        let error = parse(b"true false").unwrap_err();
500        assert_eq!(error.kind, ParseErrorKind::TrailingContent);
501    }
502
503    #[test]
504    fn reports_lone_surrogates() {
505        assert_eq!(
506            parse(br#""\uD83D""#).unwrap_err().kind,
507            ParseErrorKind::InvalidUnicodeEscape
508        );
509        assert_eq!(
510            parse(br#""\uDE00""#).unwrap_err().kind,
511            ParseErrorKind::InvalidUnicodeEscape
512        );
513    }
514
515    #[test]
516    fn reports_leading_zero_numbers() {
517        // If digits follow 0, the parser consumes only 0 and leaves trailing content.
518        assert_eq!(
519            parse(b"01").unwrap_err().kind,
520            ParseErrorKind::TrailingContent
521        );
522        assert_eq!(
523            parse(b"-01").unwrap_err().kind,
524            ParseErrorKind::TrailingContent
525        );
526    }
527
528    #[test]
529    fn parses_all_supported_number_forms() {
530        assert_eq!(parse(b"0"), Ok(JsonValue::Number(0.0)));
531        assert_eq!(parse(b"-0"), Ok(JsonValue::Number(-0.0)));
532        assert_eq!(parse(b"0.5"), Ok(JsonValue::Number(0.5)));
533        assert_eq!(parse(b"-0.5"), Ok(JsonValue::Number(-0.5)));
534        assert_eq!(parse(b"1e10"), Ok(JsonValue::Number(1e10)));
535        assert_eq!(parse(b"1E+10"), Ok(JsonValue::Number(1e10)));
536        assert_eq!(parse(b"1e-10"), Ok(JsonValue::Number(1e-10)));
537        assert_eq!(parse(b"1.5e2"), Ok(JsonValue::Number(150.0)));
538        assert_eq!(parse(b"-1.5E-3"), Ok(JsonValue::Number(-1.5e-3)));
539    }
540
541    #[test]
542    fn rejects_additional_leading_zero_forms() {
543        assert_eq!(
544            parse(b"00").unwrap_err().kind,
545            ParseErrorKind::TrailingContent
546        );
547        assert_eq!(
548            parse(b"-00").unwrap_err().kind,
549            ParseErrorKind::TrailingContent
550        );
551        assert_eq!(parse(b"-0"), Ok(JsonValue::Number(-0.0)));
552    }
553
554    #[test]
555    fn parses_solidus_escape_explicitly() {
556        assert_eq!(parse(br#""\/""#), Ok(JsonValue::String(String::from("/"))));
557    }
558
559    #[test]
560    fn accepts_all_json_whitespace_around_values() {
561        assert_eq!(parse(b"\t\r\n 42 \r\n\t"), Ok(JsonValue::Number(42.0)));
562        assert_eq!(
563            parse(b"\r\n[\t1,\n2,\r3 \t]\n"),
564            Ok(JsonValue::Array(vec![
565                JsonValue::Number(1.0),
566                JsonValue::Number(2.0),
567                JsonValue::Number(3.0),
568            ]))
569        );
570        assert_eq!(
571            parse(b"\t{\n\"a\"\r:\ttrue \n}\r"),
572            Ok(JsonValue::Object(vec![(
573                String::from("a"),
574                JsonValue::Bool(true)
575            )]))
576        );
577    }
578
579    #[test]
580    fn parses_empty_object_array_and_empty_string_key() {
581        assert_eq!(parse(b"{}"), Ok(JsonValue::Object(vec![])));
582        assert_eq!(parse(b"[]"), Ok(JsonValue::Array(vec![])));
583        assert_eq!(
584            parse(br#"{"":1}"#),
585            Ok(JsonValue::Object(vec![(
586                String::from(""),
587                JsonValue::Number(1.0)
588            )]))
589        );
590    }
591
592    #[test]
593    fn parses_unicode_escape_boundary_values() {
594        assert_eq!(
595            parse(br#""\u0000""#),
596            Ok(JsonValue::String(String::from("\u{0000}")))
597        );
598        assert_eq!(
599            parse(br#""\uFFFF""#),
600            Ok(JsonValue::String(String::from("\u{FFFF}")))
601        );
602    }
603
604    #[test]
605    fn rejects_utf8_bom_prefix() {
606        assert_eq!(
607            parse(b"\xEF\xBB\xBFnull").unwrap_err().kind,
608            ParseErrorKind::UnexpectedCharacter(0xEF)
609        );
610    }
611
612    #[test]
613    fn rejects_invalid_single_token_and_trailing_comma_inputs() {
614        for input in [b"]".as_slice(), b"}", b",", b":"] {
615            assert!(matches!(
616                parse(input).unwrap_err().kind,
617                ParseErrorKind::UnexpectedCharacter(_)
618            ));
619        }
620
621        assert_eq!(
622            parse(b"[,]").unwrap_err().kind,
623            ParseErrorKind::UnexpectedCharacter(b',')
624        );
625        assert_eq!(
626            parse(b"{,}").unwrap_err().kind,
627            ParseErrorKind::UnexpectedCharacter(b',')
628        );
629        assert_eq!(
630            parse(br#"{"key"}"#).unwrap_err().kind,
631            ParseErrorKind::UnexpectedCharacter(b'}')
632        );
633        assert_eq!(
634            parse(b"[1,]").unwrap_err().kind,
635            ParseErrorKind::UnexpectedCharacter(b']')
636        );
637    }
638
639    #[test]
640    fn reports_max_depth_exceeded() {
641        let mut input = vec![b'['; 129];
642        input.extend(vec![b']'; 129]);
643        assert_eq!(
644            parse(&input).unwrap_err().kind,
645            ParseErrorKind::NestingTooDeep
646        );
647    }
648
649    #[test]
650    fn reports_invalid_escape_sequences() {
651        assert_eq!(
652            parse(br#""\x""#).unwrap_err().kind,
653            ParseErrorKind::InvalidEscape
654        );
655    }
656
657    #[test]
658    fn reports_exact_error_positions_for_post_advance_failures() {
659        let invalid_escape = parse(br#""\x""#).unwrap_err();
660        assert_eq!(invalid_escape.kind, ParseErrorKind::InvalidEscape);
661        assert_eq!(invalid_escape.position, 2);
662
663        let invalid_literal = parse(b"tXue").unwrap_err();
664        assert_eq!(
665            invalid_literal.kind,
666            ParseErrorKind::UnexpectedCharacter(b'X')
667        );
668        assert_eq!(invalid_literal.position, 1);
669
670        let control = parse(b"\"hello\nworld\"").unwrap_err();
671        assert_eq!(control.kind, ParseErrorKind::UnexpectedCharacter(b'\n'));
672        assert_eq!(control.position, 6);
673
674        let invalid_unicode = parse(br#""\u12G4""#).unwrap_err();
675        assert_eq!(invalid_unicode.kind, ParseErrorKind::InvalidUnicodeEscape);
676        assert_eq!(invalid_unicode.position, 5);
677    }
678
679    #[test]
680    fn reports_empty_input() {
681        assert_eq!(parse(b"").unwrap_err().kind, ParseErrorKind::UnexpectedEnd);
682    }
683
684    #[test]
685    fn parses_empty_array_and_object() {
686        assert_eq!(parse(b"[]"), Ok(JsonValue::Array(vec![])));
687        assert_eq!(parse(b"{}"), Ok(JsonValue::Object(vec![])));
688    }
689
690    #[test]
691    fn parses_negative_exponent() {
692        assert_eq!(parse(b"1e-2"), Ok(JsonValue::Number(0.01)));
693        assert_eq!(parse(b"5E+3"), Ok(JsonValue::Number(5000.0)));
694    }
695
696    #[test]
697    fn parses_multibyte_utf8_in_string() {
698        // A string containing raw UTF-8 bytes.
699        assert_eq!(
700            parse("\"日本語\"".as_bytes()),
701            Ok(JsonValue::String(String::from("日本語")))
702        );
703    }
704
705    #[test]
706    fn reports_control_character_in_string() {
707        // 0x0A (newline) appears in the string without escaping.
708        assert!(parse(b"\"hello\nworld\"").is_err());
709    }
710
711    #[test]
712    fn reports_invalid_utf8_sequences_in_string() {
713        assert_eq!(
714            parse(b"\"\x80\"").unwrap_err().kind,
715            ParseErrorKind::InvalidUtf8
716        );
717        assert_eq!(
718            parse(b"\"\xC0\xAF\"").unwrap_err().kind,
719            ParseErrorKind::InvalidUtf8
720        );
721        assert_eq!(
722            parse(b"\"\xE3\x81\"").unwrap_err().kind,
723            ParseErrorKind::InvalidUtf8
724        );
725    }
726}