1use decoded_char::DecodedChar;
2use locspan::Span;
3use std::fmt;
4use utf8_decode::Utf8Error;
5
6mod array;
7mod boolean;
8mod null;
9mod number;
10mod object;
11mod string;
12mod value;
13
14use crate::JsonCodeMap;
15
16#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
18pub struct Options {
19 pub accept_truncated_surrogate_pair: bool,
25
26 pub accept_invalid_codepoints: bool,
31}
32
33impl Options {
34 pub fn strict() -> Self {
38 Self {
39 accept_truncated_surrogate_pair: false,
40 accept_invalid_codepoints: false,
41 }
42 }
43
44 pub fn flexible() -> Self {
48 Self {
49 accept_truncated_surrogate_pair: true,
50 accept_invalid_codepoints: true,
51 }
52 }
53}
54
55impl Default for Options {
56 fn default() -> Self {
57 Self::strict()
58 }
59}
60
61pub trait JsonParse: Sized {
62 fn parse_slice(content: &[u8]) -> Result<(Self, JsonCodeMap), JsonParseError> {
63 Self::parse_utf8(utf8_decode::Decoder::new(content.iter().copied()))
64 .map_err(JsonParseError::erase_utf8_error)
65 }
66
67 fn parse_slice_with(
68 content: &[u8],
69 options: Options,
70 ) -> Result<(Self, JsonCodeMap), JsonParseError> {
71 Self::parse_utf8_with(utf8_decode::Decoder::new(content.iter().copied()), options)
72 .map_err(JsonParseError::erase_utf8_error)
73 }
74
75 fn parse_str(content: &str) -> Result<(Self, JsonCodeMap), JsonParseError> {
76 Self::parse_utf8(content.chars().map(Ok))
77 }
78
79 fn parse_str_with(
80 content: &str,
81 options: Options,
82 ) -> Result<(Self, JsonCodeMap), JsonParseError> {
83 Self::parse_utf8_with(content.chars().map(Ok), options)
84 }
85
86 fn parse_infallible_utf8<C>(chars: C) -> Result<(Self, JsonCodeMap), JsonParseError>
87 where
88 C: Iterator<Item = char>,
89 {
90 Self::parse_infallible(chars.map(DecodedChar::from_utf8))
91 }
92
93 fn parse_utf8_infallible_with<C>(
94 chars: C,
95 options: Options,
96 ) -> Result<(Self, JsonCodeMap), JsonParseError>
97 where
98 C: Iterator<Item = char>,
99 {
100 Self::parse_infallible_with(chars.map(DecodedChar::from_utf8), options)
101 }
102
103 fn parse_utf8<C, E>(chars: C) -> Result<(Self, JsonCodeMap), JsonParseError<E>>
104 where
105 C: Iterator<Item = Result<char, E>>,
106 {
107 Self::parse(chars.map(|c| c.map(DecodedChar::from_utf8)))
108 }
109
110 fn parse_utf8_with<C, E>(
111 chars: C,
112 options: Options,
113 ) -> Result<(Self, JsonCodeMap), JsonParseError<E>>
114 where
115 C: Iterator<Item = Result<char, E>>,
116 {
117 Self::parse_with(chars.map(|c| c.map(DecodedChar::from_utf8)), options)
118 }
119
120 fn parse_infallible<C>(chars: C) -> Result<(Self, JsonCodeMap), JsonParseError>
121 where
122 C: Iterator<Item = DecodedChar>,
123 {
124 let mut parser = Parser::new(chars.map(Ok));
125 let value = Self::parse_in(&mut parser, JsonParsingContext::None)?.0;
126 Ok((value, parser.code_map))
127 }
128
129 fn parse_infallible_with<C>(
130 chars: C,
131 options: Options,
132 ) -> Result<(Self, JsonCodeMap), JsonParseError>
133 where
134 C: Iterator<Item = DecodedChar>,
135 {
136 let mut parser = Parser::new_with(chars.map(Ok), options);
137 let value = Self::parse_in(&mut parser, JsonParsingContext::None)?.0;
138 Ok((value, parser.code_map))
139 }
140
141 fn parse<C, E>(chars: C) -> Result<(Self, JsonCodeMap), JsonParseError<E>>
142 where
143 C: Iterator<Item = Result<DecodedChar, E>>,
144 {
145 let mut parser = Parser::new(chars);
146 let value = Self::parse_in(&mut parser, JsonParsingContext::None)?.0;
147 Ok((value, parser.code_map))
148 }
149
150 fn parse_with<C, E>(
151 chars: C,
152 options: Options,
153 ) -> Result<(Self, JsonCodeMap), JsonParseError<E>>
154 where
155 C: Iterator<Item = Result<DecodedChar, E>>,
156 {
157 let mut parser = Parser::new_with(chars, options);
158 let value = Self::parse_in(&mut parser, JsonParsingContext::None)?.0;
159 Ok((value, parser.code_map))
160 }
161
162 fn parse_in<C, E>(
163 parser: &mut Parser<C, E>,
164 context: JsonParsingContext,
165 ) -> Result<(Self, usize), JsonParseError<E>>
166 where
167 C: Iterator<Item = Result<DecodedChar, E>>;
168}
169
170pub struct Parser<C: Iterator<Item = Result<DecodedChar, E>>, E> {
172 chars: C,
174
175 pending: Option<DecodedChar>,
177
178 position: usize,
180
181 options: Options,
183
184 code_map: JsonCodeMap,
186}
187
188#[inline(always)]
190pub fn is_whitespace(c: char) -> bool {
191 matches!(c, ' ' | '\t' | '\r' | '\n')
192}
193
194impl<C: Iterator<Item = Result<DecodedChar, E>>, E> Parser<C, E> {
195 pub fn new(chars: C) -> Self {
196 Self {
197 chars,
198 pending: None,
199 position: 0,
200 options: Options::default(),
201 code_map: JsonCodeMap::default(),
202 }
203 }
204
205 pub fn new_with(chars: C, options: Options) -> Self {
206 Self {
207 chars,
208 pending: None,
209 position: 0,
210 options,
211 code_map: JsonCodeMap::default(),
212 }
213 }
214
215 fn begin_fragment(&mut self) -> usize {
216 self.code_map.reserve(self.position)
217 }
218
219 fn end_fragment(&mut self, i: usize) {
220 let entry_count = self.code_map.len();
221 let entry = self.code_map.get_mut(i).unwrap();
222 entry.span.end = self.position;
223 entry.volume = entry_count - i;
224 }
225
226 fn peek_char(&mut self) -> Result<Option<char>, JsonParseError<E>> {
227 match self.pending {
228 Some(c) => Ok(Some(c.chr())),
229 None => match self.chars.next() {
230 Some(Ok(c)) => {
231 self.pending = Some(c);
232 Ok(Some(c.chr()))
233 }
234 Some(Err(e)) => Err(JsonParseError::Stream(self.position, e)),
235 None => Ok(None),
236 },
237 }
238 }
239
240 fn next_char(&mut self) -> Result<(usize, Option<char>), JsonParseError<E>> {
241 let c = match self.pending.take() {
242 Some(c) => Some(c),
243 None => self
244 .chars
245 .next()
246 .transpose()
247 .map_err(|e| JsonParseError::Stream(self.position, e))?,
248 };
249
250 let p = self.position;
251 let c = c.map(|c| {
252 self.position += c.len();
253 c.chr()
254 });
255
256 Ok((p, c))
257 }
258
259 fn skip_whitespaces(&mut self) -> Result<(), JsonParseError<E>> {
260 while let Some(c) = self.peek_char()? {
261 if is_whitespace(c) {
262 self.next_char()?;
263 } else {
264 break;
265 }
266 }
267
268 Ok(())
269 }
270}
271
272#[derive(Debug)]
274pub enum JsonParseError<E = core::convert::Infallible> {
275 Stream(usize, E),
279
280 Unexpected(usize, Option<char>),
284
285 InvalidUnicodeCodePoint(Span, u32),
289
290 MissingLowSurrogate(Span, u16),
294
295 InvalidLowSurrogate(Span, u16, u32),
299
300 InvalidUtf8(usize),
302}
303
304impl<E> JsonParseError<E> {
305 #[inline(always)]
307 fn unexpected(position: usize, c: Option<char>) -> Self {
308 Self::Unexpected(position, c)
310 }
311
312 pub fn position(&self) -> usize {
313 match self {
314 Self::Stream(p, _) => *p,
315 Self::Unexpected(p, _) => *p,
316 Self::InvalidUnicodeCodePoint(span, _) => span.start,
317 Self::MissingLowSurrogate(span, _) => span.start,
318 Self::InvalidLowSurrogate(span, _, _) => span.start,
319 Self::InvalidUtf8(p) => *p,
320 }
321 }
322
323 pub fn span(&self) -> Span {
324 match self {
325 Self::Stream(p, _) => Span::new(*p, *p),
326 Self::Unexpected(p, _) => Span::new(*p, *p),
327 Self::InvalidUnicodeCodePoint(span, _) => *span,
328 Self::MissingLowSurrogate(span, _) => *span,
329 Self::InvalidLowSurrogate(span, _, _) => *span,
330 Self::InvalidUtf8(p) => Span::new(*p, *p),
331 }
332 }
333}
334
335impl JsonParseError<Utf8Error> {
336 fn erase_utf8_error(self) -> JsonParseError {
337 match self {
338 Self::Stream(p, _) => JsonParseError::InvalidUtf8(p),
339 Self::Unexpected(p, e) => JsonParseError::Unexpected(p, e),
340 Self::InvalidUnicodeCodePoint(s, e) => JsonParseError::InvalidUnicodeCodePoint(s, e),
341 Self::MissingLowSurrogate(s, e) => JsonParseError::MissingLowSurrogate(s, e),
342 Self::InvalidLowSurrogate(s, a, b) => JsonParseError::InvalidLowSurrogate(s, a, b),
343 Self::InvalidUtf8(p) => JsonParseError::InvalidUtf8(p),
344 }
345 }
346}
347
348impl<E: fmt::Display> fmt::Display for JsonParseError<E> {
349 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350 match self {
351 Self::Stream(_, e) => e.fmt(f),
352 Self::Unexpected(_, Some(c)) => write!(f, "unexpected character `{}`", c),
353 Self::Unexpected(_, None) => write!(f, "unexpected end of file"),
354 Self::InvalidUnicodeCodePoint(_, c) => write!(f, "invalid Unicode code point {:x}", *c),
355 Self::MissingLowSurrogate(_, _) => write!(f, "missing low surrogate"),
356 Self::InvalidLowSurrogate(_, _, _) => write!(f, "invalid low surrogate"),
357 Self::InvalidUtf8(_) => write!(f, "invalid UTF-8"),
358 }
359 }
360}
361
362impl<E: 'static + std::error::Error> std::error::Error for JsonParseError<E> {
363 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
364 match self {
365 Self::Stream(_, e) => Some(e),
366 _ => None,
367 }
368 }
369}
370
371#[derive(Clone, Copy, PartialEq, Eq, Debug)]
375pub enum JsonParsingContext {
376 None,
377 Array,
378 ObjectKey,
379 ObjectValue,
380}
381
382impl JsonParsingContext {
383 pub fn follows(&self, c: char) -> bool {
385 match self {
386 Self::None => is_whitespace(c),
387 Self::Array => is_whitespace(c) || matches!(c, ',' | ']'),
388 Self::ObjectKey => is_whitespace(c) || matches!(c, ':'),
389 Self::ObjectValue => is_whitespace(c) || matches!(c, ',' | '}'),
390 }
391 }
392}