1use super::{JsonParse, JsonParseError, JsonParsingContext, Parser};
2use decoded_char::DecodedChar;
3use locspan::Span;
4use smallstr::SmallString;
5
6fn is_control(c: char) -> bool {
7 ('\u{0000}'..='\u{001f}').contains(&c)
8}
9
10fn parse_hex4<C, E>(parser: &mut Parser<C, E>) -> Result<u32, JsonParseError<E>>
11where
12 C: Iterator<Item = Result<DecodedChar, E>>,
13{
14 match parser.next_char()? {
15 (p, Some(c)) => match c.to_digit(16) {
16 Some(h3) => match parser.next_char()? {
17 (p, Some(c)) => match c.to_digit(16) {
18 Some(h2) => match parser.next_char()? {
19 (p, Some(c)) => match c.to_digit(16) {
20 Some(h1) => match parser.next_char()? {
21 (p, Some(c)) => match c.to_digit(16) {
22 Some(h0) => Ok(h3 << 12 | h2 << 8 | h1 << 4 | h0),
23 None => Err(JsonParseError::unexpected(p, Some(c))),
24 },
25 (p, unexpected) => Err(JsonParseError::unexpected(p, unexpected)),
26 },
27 None => Err(JsonParseError::unexpected(p, Some(c))),
28 },
29 (p, unexpected) => Err(JsonParseError::unexpected(p, unexpected)),
30 },
31 None => Err(JsonParseError::unexpected(p, Some(c))),
32 },
33 (p, unexpected) => Err(JsonParseError::unexpected(p, unexpected)),
34 },
35 None => Err(JsonParseError::unexpected(p, Some(c))),
36 },
37 (p, unexpected) => Err(JsonParseError::unexpected(p, unexpected)),
38 }
39}
40
41impl<A: smallvec::Array<Item = u8>> JsonParse for SmallString<A> {
42 fn parse_in<C, E>(
43 parser: &mut Parser<C, E>,
44 _context: JsonParsingContext,
45 ) -> Result<(Self, usize), JsonParseError<E>>
46 where
47 C: Iterator<Item = Result<DecodedChar, E>>,
48 {
49 let i = parser.begin_fragment();
50 match parser.next_char()? {
51 (_, Some('"')) => {
52 let mut result = Self::new();
53 let mut high_surrogate: Option<(usize, u32)> = None;
54 loop {
55 let c = match parser.next_char()? {
56 (p, Some('"')) => {
57 if let Some((p_high, high)) = high_surrogate {
58 if parser.options.accept_truncated_surrogate_pair {
59 result.push('\u{fffd}');
60 } else {
61 break Err(JsonParseError::MissingLowSurrogate(
62 Span::new(p_high, p),
63 high as u16,
64 ));
65 }
66 }
67
68 parser.end_fragment(i);
69 break Ok((result, i));
70 }
71 (_, Some('\\')) => {
72 match parser.next_char()? {
73 (_, Some(c @ ('"' | '\\' | '/'))) => c,
74 (_, Some('b')) => '\u{0008}',
75 (_, Some('t')) => '\u{0009}',
76 (_, Some('n')) => '\u{000a}',
77 (_, Some('f')) => '\u{000c}',
78 (_, Some('r')) => '\u{000d}',
79 (p, Some('u')) => {
80 let codepoint = parse_hex4(parser)?;
81
82 match high_surrogate.take() {
83 Some((p_high, high)) => {
84 if (0xdc00..=0xdfff).contains(&codepoint) {
85 let low = codepoint;
86 let codepoint = ((high - 0xd800) << 10
87 | (low - 0xdc00)) + 0x010000;
88 match char::from_u32(codepoint) {
89 Some(c) => c,
90 None => {
91 if parser.options.accept_invalid_codepoints
92 {
93 '\u{fffd}'
94 } else {
95 break Err(JsonParseError::InvalidUnicodeCodePoint(
96 Span::new(p_high, parser.position),
97 codepoint,
98 ));
99 }
100 }
101 }
102 } else if parser.options.accept_truncated_surrogate_pair
103 {
104 result.push('\u{fffd}');
105
106 match char::from_u32(codepoint) {
107 Some(c) => c,
108 None => {
109 if parser.options.accept_invalid_codepoints
110 {
111 '\u{fffd}'
112 } else {
113 break Err(JsonParseError::InvalidUnicodeCodePoint(
114 Span::new(p, parser.position),
115 codepoint,
116 ));
117 }
118 }
119 }
120 } else {
121 break Err(JsonParseError::InvalidLowSurrogate(
122 Span::new(p, parser.position),
123 high as u16,
124 codepoint,
125 ));
126 }
127 }
128 None => {
129 if (0xd800..=0xdbff).contains(&codepoint) {
130 high_surrogate = Some((p, codepoint));
131 continue;
132 } else {
133 match char::from_u32(codepoint) {
134 Some(c) => c,
135 None => {
136 if parser.options.accept_invalid_codepoints
137 {
138 '\u{fffd}'
139 } else {
140 break Err(JsonParseError::InvalidUnicodeCodePoint(
141 Span::new(p, parser.position),
142 codepoint,
143 ));
144 }
145 }
146 }
147 }
148 }
149 }
150 }
151 (p, unexpected) => {
152 break Err(JsonParseError::unexpected(p, unexpected));
153 }
154 }
155 }
156 (_, Some(c)) if !is_control(c) => c,
157 (p, unexpected) => break Err(JsonParseError::unexpected(p, unexpected)),
158 };
159
160 if let Some((p_high, high)) = high_surrogate.take() {
161 if parser.options.accept_truncated_surrogate_pair {
162 result.push('\u{fffd}');
163 } else {
164 break Err(JsonParseError::MissingLowSurrogate(
165 Span::new(p_high, parser.position),
166 high as u16,
167 ));
168 }
169 }
170
171 result.push(c);
172 }
173 }
174 (p, unexpected) => Err(JsonParseError::unexpected(p, unexpected)),
175 }
176 }
177}