1#[cfg(test)]
3pub(crate) mod test;
4
5#[cfg(test)]
6mod test_basic_happy_structure;
7
8#[cfg(test)]
9mod test_error_reporting;
10
11#[cfg(test)]
12mod test_type_sizes;
13
14#[cfg(test)]
15mod test_line_col;
16
17#[cfg(test)]
18mod test_raw_str;
19
20#[cfg(test)]
21mod test_parser;
22
23use std::borrow::{Borrow, Cow};
24use std::fmt;
25use std::iter::Peekable;
26use std::num::TryFromIntError;
27use std::str::Bytes;
28use std::sync::atomic::AtomicUsize;
29use std::sync::Arc;
30
31use json_tools::{Buffer, BufferType};
32use tracing::{debug, trace};
33
34use crate::{warning, Caveat, ReasonableStr};
35
36use super::{
37 decode::{self, unescape_str},
38 Element, Field, ObjectKind, PathNode, PathNodeRef, Value, ValueKind,
39};
40use super::{ElemId, Path};
41
42type Lexer<'buf> = Peekable<json_tools::Lexer<Bytes<'buf>>>;
44
45pub(crate) fn parse(json: ReasonableStr<'_>) -> Result<Element<'_>, Error> {
47 let parser = Parser::new(json.into_inner());
48
49 for event in parser {
52 if let Event::Complete(element) = event? {
53 return Ok(element);
54 }
55 }
56
57 Err(ErrorKind::UnexpectedEOF
58 .into_partial_error_without_token()
59 .with_root_path())
60}
61
62#[derive(Debug)]
64pub(crate) enum Event<'buf> {
65 Open {
67 kind: ObjectKind,
68 parent_path: PathNodeRef<'buf>,
69 },
70
71 Element {
75 kind: ValueKind,
77 parent_path: PathNodeRef<'buf>,
79 },
80
81 Complete(Element<'buf>),
83}
84
85pub(crate) struct Parser<'buf> {
87 elem_count: AtomicUsize,
89
90 complete: bool,
94
95 json: &'buf str,
97
98 lexer: Lexer<'buf>,
100
101 path_pool: PathPool<'buf>,
103
104 stack: Stack<'buf>,
106
107 token: Option<Token>,
109}
110
111#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
115pub enum TokenType {
116 BooleanFalse,
118 BooleanTrue,
120
121 BracketClose,
123 BracketOpen,
125
126 Colon,
128
129 Comma,
131
132 CurlyClose,
134 CurlyOpen,
136
137 Invalid,
140
141 Null,
143
144 Number,
146
147 String,
149}
150
151impl TokenType {
152 fn as_str(self) -> &'static str {
153 match self {
154 TokenType::BooleanFalse => "false",
155 TokenType::BooleanTrue => "true",
156 TokenType::BracketClose => "]",
157 TokenType::BracketOpen => "[",
158 TokenType::Colon => ":",
159 TokenType::Comma => ",",
160 TokenType::CurlyClose => "}",
161 TokenType::CurlyOpen => "{",
162 TokenType::Invalid => "<invalid>",
163 TokenType::Null => "null",
164 TokenType::Number => "<number>",
165 TokenType::String => "<string>",
166 }
167 }
168}
169
170impl fmt::Display for TokenType {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 f.write_str(self.as_str())
173 }
174}
175
176impl From<json_tools::TokenType> for TokenType {
177 fn from(value: json_tools::TokenType) -> Self {
178 match value {
179 json_tools::TokenType::BooleanFalse => TokenType::BooleanFalse,
180 json_tools::TokenType::BooleanTrue => TokenType::BooleanTrue,
181 json_tools::TokenType::BracketClose => TokenType::BracketClose,
182 json_tools::TokenType::BracketOpen => TokenType::BracketOpen,
183 json_tools::TokenType::CurlyClose => TokenType::CurlyClose,
184 json_tools::TokenType::CurlyOpen => TokenType::CurlyOpen,
185 json_tools::TokenType::Colon => TokenType::Colon,
186 json_tools::TokenType::Comma => TokenType::Comma,
187 json_tools::TokenType::Invalid => TokenType::Invalid,
188 json_tools::TokenType::Null => TokenType::Null,
189 json_tools::TokenType::Number => TokenType::Number,
190 json_tools::TokenType::String => TokenType::String,
191 }
192 }
193}
194
195#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
202pub struct Token {
203 pub kind: TokenType,
205
206 pub span: Span,
209}
210
211impl Token {
212 fn is_opening(&self) -> bool {
214 matches!(self.kind, TokenType::CurlyOpen | TokenType::BracketOpen)
215 }
216
217 fn is_closing(&self) -> bool {
219 matches!(self.kind, TokenType::CurlyClose | TokenType::BracketClose)
220 }
221
222 fn is_comma(&self) -> bool {
224 matches!(self.kind, TokenType::Comma)
225 }
226}
227
228impl fmt::Display for Token {
229 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
230 write!(
231 f,
232 "token: {}, ({},{})",
233 self.kind, self.span.start, self.span.end
234 )
235 }
236}
237
238impl TryFrom<json_tools::Token> for Token {
239 type Error = PartialError;
240
241 fn try_from(token: json_tools::Token) -> Result<Self, Self::Error> {
242 let json_tools::Token { kind, buf } = token;
243 let kind = kind.into();
244 let Buffer::Span(span) = &buf else {
245 return Err(InternalError::BufferType.into_partial_error(None));
246 };
247
248 let span = span
249 .try_into()
250 .map_err(|err| InternalError::from(err).into_partial_error(None))?;
251
252 Ok(Self { kind, span })
253 }
254}
255
256impl TryFrom<&json_tools::Token> for Token {
257 type Error = PartialError;
258
259 fn try_from(token: &json_tools::Token) -> Result<Self, Self::Error> {
260 let json_tools::Token { kind, buf } = token;
261 let kind = kind.clone().into();
262 let Buffer::Span(span) = &buf else {
263 return Err(InternalError::BufferType.into_partial_error(None));
264 };
265
266 let span = span
267 .try_into()
268 .map_err(|err| InternalError::from(err).into_partial_error(None))?;
269
270 Ok(Self { kind, span })
271 }
272}
273
274impl<'buf> Parser<'buf> {
275 pub fn new(json: &'buf str) -> Self {
276 let lexer = json_tools::Lexer::new(json.bytes(), BufferType::Span).peekable();
277
278 Self {
279 elem_count: AtomicUsize::new(0),
280 complete: false,
281 json,
282 lexer,
283 path_pool: PathPool::default(),
284 stack: Stack::new(),
285 token: None,
286 }
287 }
288
289 fn next_elem_id(&self) -> ElemId {
290 let id = self
291 .elem_count
292 .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
293
294 ElemId(id)
295 }
296
297 fn expect_next(&mut self) -> Result<Token, PartialError> {
298 let Some(token) = self.lexer.next() else {
299 return Err(ErrorKind::UnexpectedEOF.into_partial_error(self.token.take()));
300 };
301
302 let token = token.try_into()?;
303
304 Ok(token)
305 }
306
307 fn expect_token(&mut self, token_type: TokenType) -> Result<(), PartialError> {
309 let Some(token) = self.lexer.next() else {
310 return Err(ErrorKind::UnexpectedEOF.into_partial_error(self.token.take()));
311 };
312
313 let token: Token = token.try_into()?;
314
315 if token.kind == token_type {
316 Ok(())
317 } else {
318 Err(unexpected_token(token))
319 }
320 }
321
322 #[expect(
323 clippy::cognitive_complexity,
324 reason = "Lifetimes make splitting this function more effort than it's worth"
325 )]
326 fn next_event(&mut self) -> Result<Option<Event<'buf>>, Error> {
327 if self.complete {
328 return Ok(None);
329 }
330
331 let head = self.stack.pop_head();
332
333 match head {
334 None => {
335 let token = self.expect_next().with_root_path()?;
336
337 trace!(?token);
338 self.comma_checks(&token).with_root_path()?;
339
340 match token.kind {
341 TokenType::CurlyOpen => {
342 let parent_path = self.path_pool.root();
343 self.stack.push_new_object(
344 self.next_elem_id(),
345 Arc::clone(&parent_path),
346 &token,
347 );
348 Ok(Some(Event::Open {
349 kind: ObjectKind::Object,
350 parent_path,
351 }))
352 }
353 TokenType::BracketOpen => {
354 let parent_path = self.path_pool.root();
355 self.stack.push_new_array(
356 self.next_elem_id(),
357 Arc::clone(&parent_path),
358 &token,
359 );
360 Ok(Some(Event::Open {
361 kind: ObjectKind::Array,
362 parent_path,
363 }))
364 }
365 TokenType::Number => {
366 let value = Value::Number(token_str(self.json, &token).with_root_path()?);
367 self.exit_with_value(token, value).with_root_path()
368 }
369 TokenType::Null => self.exit_with_value(token, Value::Null).with_root_path(),
370 TokenType::String => {
371 let value =
372 Value::String(token_str_as_string(self.json, token).with_root_path()?);
373 self.exit_with_value(token, value).with_root_path()
374 }
375 TokenType::BooleanTrue => {
376 self.exit_with_value(token, Value::True).with_root_path()
377 }
378 TokenType::BooleanFalse => {
379 self.exit_with_value(token, Value::False).with_root_path()
380 }
381 TokenType::BracketClose
382 | TokenType::Colon
383 | TokenType::Comma
384 | TokenType::CurlyClose
385 | TokenType::Invalid => Err(unexpected_token(token).with_root_path()),
386 }
387 }
388 Some(mut head) => {
389 let token = self.expect_next().with_head(&head)?;
390
391 trace!(?token, head = ?head.elem_type);
392 let token = if self.comma_checks(&token).with_head(&head)? {
393 self.expect_next().with_head(&head)?
394 } else {
395 token
396 };
397
398 let (value, token, path) = match head.elem_type {
399 ObjectKind::Object => {
400 let key = match token.kind {
401 TokenType::String => {
402 token_str_as_string(self.json, token).with_head(&head)?
403 }
404 TokenType::CurlyClose => {
405 let event = self.close_element(head, &token)?;
406 return Ok(event);
407 }
408 TokenType::BooleanFalse
409 | TokenType::BooleanTrue
410 | TokenType::BracketClose
411 | TokenType::BracketOpen
412 | TokenType::Colon
413 | TokenType::Comma
414 | TokenType::CurlyOpen
415 | TokenType::Invalid
416 | TokenType::Null
417 | TokenType::Number => {
418 return Err(unexpected_token(token).with_root_path())
419 }
420 };
421
422 self.expect_token(TokenType::Colon).with_head(&head)?;
423 let token = self.expect_next().with_head(&head)?;
424
425 let value = match token.kind {
426 TokenType::CurlyOpen => {
427 let Some(parent_path) =
428 head.parent_is_object(&mut self.path_pool, key)
429 else {
430 return Ok(None);
431 };
432 self.stack.push_head(head);
433 self.stack.push_new_object(
434 self.next_elem_id(),
435 Arc::clone(&parent_path),
436 &token,
437 );
438 return Ok(Some(Event::Open {
439 kind: ObjectKind::Object,
440 parent_path,
441 }));
442 }
443 TokenType::BracketOpen => {
444 let Some(parent_path) =
445 head.parent_is_object(&mut self.path_pool, key)
446 else {
447 return Ok(None);
448 };
449 self.stack.push_head(head);
450 self.stack.push_new_array(
451 self.next_elem_id(),
452 Arc::clone(&parent_path),
453 &token,
454 );
455 return Ok(Some(Event::Open {
456 kind: ObjectKind::Array,
457 parent_path,
458 }));
459 }
460 TokenType::CurlyClose => {
461 let event = self.close_element(head, &token)?;
462 return Ok(event);
463 }
464 TokenType::String => Value::String(
465 token_str_as_string(self.json, token).with_head(&head)?,
466 ),
467 TokenType::Number => {
468 Value::Number(token_str(self.json, &token).with_head(&head)?)
469 }
470 TokenType::Null => Value::Null,
471 TokenType::BooleanTrue => Value::True,
472 TokenType::BooleanFalse => Value::False,
473 TokenType::BracketClose
474 | TokenType::Colon
475 | TokenType::Comma
476 | TokenType::Invalid => {
477 return Err(unexpected_token(token).with_head(&head))
478 }
479 };
480
481 let Some(path) = head.parent_is_object(&mut self.path_pool, key) else {
482 return Ok(None);
483 };
484 (value, token, path)
485 }
486 ObjectKind::Array => {
487 let value = match token.kind {
488 TokenType::CurlyOpen => {
489 let Some(parent_path) = head.parent_is_array(&mut self.path_pool)
490 else {
491 return Ok(None);
492 };
493 self.stack.push_head(head);
494 self.stack.push_new_object(
495 self.next_elem_id(),
496 Arc::clone(&parent_path),
497 &token,
498 );
499 return Ok(Some(Event::Open {
500 kind: ObjectKind::Object,
501 parent_path,
502 }));
503 }
504 TokenType::BracketOpen => {
505 let Some(parent_path) = head.parent_is_array(&mut self.path_pool)
506 else {
507 return Ok(None);
508 };
509 self.stack.push_head(head);
510 self.stack.push_new_array(
511 self.next_elem_id(),
512 Arc::clone(&parent_path),
513 &token,
514 );
515 return Ok(Some(Event::Open {
516 kind: ObjectKind::Array,
517 parent_path,
518 }));
519 }
520 TokenType::BracketClose => {
521 let event = self.close_element(head, &token)?;
522 return Ok(event);
523 }
524
525 TokenType::String => Value::String(
526 token_str_as_string(self.json, token).with_head(&head)?,
527 ),
528 TokenType::Number => {
529 Value::Number(token_str(self.json, &token).with_head(&head)?)
530 }
531 TokenType::Null => Value::Null,
532 TokenType::BooleanTrue => Value::True,
533 TokenType::BooleanFalse => Value::False,
534 TokenType::Invalid
535 | TokenType::CurlyClose
536 | TokenType::Colon
537 | TokenType::Comma => {
538 return Err(unexpected_token(token).with_head(&head))
539 }
540 };
541 let Some(path) = head.parent_is_array(&mut self.path_pool) else {
542 return Ok(None);
543 };
544 (value, token, path)
545 }
546 };
547
548 let event = Event::Element {
549 kind: value.kind(),
550 parent_path: Arc::clone(&path),
551 };
552 head.push_field(self.next_elem_id(), path, value, &token);
553
554 let peek_token = self.peek(&token).with_head(&head)?;
555
556 if !(peek_token.is_comma() || peek_token.is_closing()) {
557 return Err(unexpected_token(peek_token).with_head(&head));
558 }
559
560 self.token.replace(token);
561 self.stack.push_head(head);
562
563 Ok(Some(event))
564 }
565 }
566 }
567
568 fn close_element(
570 &mut self,
571 head: PartialElement<'buf>,
572 token: &Token,
573 ) -> Result<Option<Event<'buf>>, Error> {
574 let event = self.stack.head_into_element(head, token);
575
576 match event {
577 Pop::Element { kind, parent_path } => Ok(Some(Event::Element { kind, parent_path })),
578 Pop::Complete(element) => {
579 if let Some(token) = self.lexer.next() {
580 let token = token.try_into().with_root_path()?;
581 return Err(unexpected_token(token).with_root_path());
582 }
583
584 Ok(Some(Event::Complete(element)))
585 }
586 }
587 }
588
589 fn exit_with_value(
590 &mut self,
591 token: Token,
592 value: Value<'buf>,
593 ) -> Result<Option<Event<'buf>>, PartialError> {
594 self.complete = true;
595 let span = element_span(&token, 0);
596 let elem = Element::new(self.next_elem_id(), Arc::new(PathNode::Root), span, value);
597
598 if let Some(token) = self.lexer.next() {
599 let token = token.try_into()?;
600 return Err(unexpected_token(token));
601 }
602
603 Ok(Some(Event::Complete(elem)))
604 }
605
606 fn peek(&mut self, token: &Token) -> Result<Token, PartialError> {
607 let Some(peek_token) = self.lexer.peek() else {
608 return Err(ErrorKind::UnexpectedEOF.into_partial_error(Some(*token)));
609 };
610
611 let peek_token = peek_token.try_into()?;
612 Ok(peek_token)
613 }
614
615 fn comma_checks(&mut self, token: &Token) -> Result<bool, PartialError> {
619 trace!(?token, "comma_checks");
620 let is_comma = token.is_comma();
621
622 if is_comma {
623 let peek_token = self.peek(token)?;
624
625 if peek_token.is_closing() {
627 return Err(unexpected_token(*token));
628 }
629
630 if peek_token.is_comma() {
631 return Err(unexpected_token(peek_token));
632 }
633 } else if token.is_opening() {
634 let peek_token = self.peek(token)?;
635
636 if peek_token.is_comma() {
638 return Err(unexpected_token(peek_token));
639 }
640 }
641
642 Ok(is_comma)
643 }
644}
645
646#[track_caller]
648fn unexpected_token(token: Token) -> PartialError {
649 ErrorKind::UnexpectedToken.into_partial_error(Some(token))
650}
651
652impl<'buf> Iterator for Parser<'buf> {
653 type Item = Result<Event<'buf>, Error>;
654
655 fn next(&mut self) -> Option<Self::Item> {
656 match self.next_event() {
657 Ok(event) => event.map(Ok),
658 Err(err) => {
659 self.complete = true;
660 Some(Err(err))
661 }
662 }
663 }
664}
665
666#[derive(Debug)]
668struct PartialElement<'buf> {
669 elem_id: ElemId,
671
672 elem_type: ObjectKind,
674
675 elements: Vec<Element<'buf>>,
679
680 path: PathNodeRef<'buf>,
682
683 span_start: usize,
685}
686
687impl<'buf> PartialElement<'buf> {
688 fn parent_is_object(
689 &self,
690 path_pool: &mut PathPool<'buf>,
691 key: RawStr<'buf>,
692 ) -> Option<PathNodeRef<'buf>> {
693 path_pool.object(Arc::clone(&self.path), key)
694 }
695
696 fn parent_is_array(&self, path_pool: &mut PathPool<'buf>) -> Option<PathNodeRef<'buf>> {
697 path_pool.array(Arc::clone(&self.path), self.elements.len())
698 }
699
700 fn push_field(
701 &mut self,
702 elem_id: ElemId,
703 path: PathNodeRef<'buf>,
704 value: Value<'buf>,
705 token: &Token,
706 ) {
707 let span = element_span(token, token.span.start);
708 let elem = Element::new(elem_id, path, span, value);
709 self.elements.push(elem);
710 }
711
712 fn into_element(self, token: &Token) -> Element<'buf> {
714 let span = element_span(token, self.span_start);
715
716 let PartialElement {
717 elem_type,
718 span_start: _,
719 elements,
720 path,
721 elem_id,
722 } = self;
723
724 let value = match elem_type {
725 ObjectKind::Object => {
726 let fields = elements.into_iter().map(Field).collect();
727 Value::Object(fields)
728 }
729 ObjectKind::Array => Value::Array(elements),
730 };
731
732 Element::new(elem_id, path, span, value)
733 }
734}
735
736struct PathPool<'buf> {
738 index: usize,
739 items: Vec<PathNodeRef<'buf>>,
740}
741
742impl Default for PathPool<'_> {
743 fn default() -> Self {
744 Self::with_capacity(1000)
745 }
746}
747
748impl<'buf> PathPool<'buf> {
749 fn with_capacity(capacity: usize) -> Self {
750 let capacity = capacity.max(1);
751 let mut items = Vec::with_capacity(capacity);
752 items.resize_with(capacity, Default::default);
753
754 Self { index: 0, items }
755 }
756
757 #[expect(
758 clippy::indexing_slicing,
759 reason = "The root Path is added in the constructor and the capacity is always at least 1"
760 )]
761 fn root(&self) -> PathNodeRef<'buf> {
762 Arc::clone(&self.items[0])
763 }
764
765 fn array(&mut self, parent: PathNodeRef<'buf>, index: usize) -> Option<PathNodeRef<'buf>> {
767 self.push(PathNode::Array { parent, index })
768 }
769
770 fn object(
772 &mut self,
773 parent: PathNodeRef<'buf>,
774 key: RawStr<'buf>,
775 ) -> Option<PathNodeRef<'buf>> {
776 self.push(PathNode::Object { parent, key })
777 }
778
779 fn push(&mut self, new_path: PathNode<'buf>) -> Option<PathNodeRef<'buf>> {
780 const GROWTH_FACTOR: usize = 2;
781
782 let Self { index, items } = self;
783 let next_index = index.checked_add(1)?;
784
785 if next_index >= items.len() {
786 items.reserve(items.len().saturating_mul(GROWTH_FACTOR));
787 items.resize_with(items.capacity(), Default::default);
788 }
789
790 let path = items.get_mut(next_index)?;
791 debug_assert_eq!(Arc::strong_count(path), 1, "Paths are only added");
792 let path = Arc::get_mut(path)?;
793 *path = new_path;
794
795 let path = items.get_mut(next_index)?;
796 let path_result = Arc::clone(path);
797
798 *index = next_index;
799 Some(path_result)
800 }
801}
802
803#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
805pub struct Span {
806 pub start: usize,
808
809 pub end: usize,
811}
812
813impl TryFrom<&json_tools::Span> for Span {
814 type Error = TryFromIntError;
815
816 fn try_from(span: &json_tools::Span) -> Result<Self, Self::Error> {
817 let json_tools::Span { first, end } = span;
818 let start = usize::try_from(*first)?;
819 let end = usize::try_from(*end)?;
820 Ok(Span { start, end })
821 }
822}
823
824struct Stack<'buf>(Vec<PartialElement<'buf>>);
825
826enum Pop<'buf> {
827 Element {
829 kind: ValueKind,
830 parent_path: PathNodeRef<'buf>,
831 },
832
833 Complete(Element<'buf>),
835}
836
837impl<'buf> Stack<'buf> {
838 fn new() -> Self {
839 Self(vec![])
840 }
841
842 fn pop_head(&mut self) -> Option<PartialElement<'buf>> {
845 self.0.pop()
846 }
847
848 fn push_head(&mut self, head: PartialElement<'buf>) {
851 self.0.push(head);
852 }
853
854 fn head_into_element(&mut self, head: PartialElement<'buf>, token: &Token) -> Pop<'buf> {
856 let elem = head.into_element(token);
857
858 if let Some(parent) = self.0.last_mut() {
859 let event = Pop::Element {
860 kind: elem.value.kind(),
861 parent_path: elem.path_node(),
862 };
863 parent.elements.push(elem);
864 event
865 } else {
866 Pop::Complete(elem)
867 }
868 }
869
870 fn push_new_object(&mut self, elem_id: ElemId, parent_path: PathNodeRef<'buf>, token: &Token) {
871 self.push_new_elem(elem_id, parent_path, token, ObjectKind::Object);
872 }
873
874 fn push_new_array(&mut self, elem_id: ElemId, parent_path: PathNodeRef<'buf>, token: &Token) {
875 self.push_new_elem(elem_id, parent_path, token, ObjectKind::Array);
876 }
877
878 fn push_new_elem(
879 &mut self,
880 elem_id: ElemId,
881 parent_path: PathNodeRef<'buf>,
882 token: &Token,
883 elem_type: ObjectKind,
884 ) {
885 let partial = PartialElement {
886 elements: vec![],
887 elem_type,
888 path: parent_path,
889 span_start: token.span.start,
890 elem_id,
891 };
892 self.0.push(partial);
893 }
894}
895
896pub struct Error(Box<ErrorImpl>);
899
900impl crate::Warning for Error {
901 fn id(&self) -> warning::Id {
902 match self.0.kind {
903 ErrorKind::Internal(_) => warning::Id::from_static("internal"),
904 ErrorKind::UnexpectedEOF => warning::Id::from_static("unexpected_eof"),
905 ErrorKind::UnexpectedToken => warning::Id::from_static("unexpected_token"),
906 }
907 }
908}
909
910impl fmt::Debug for Error {
911 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
912 fmt::Debug::fmt(&self.0, f)
913 }
914}
915
916impl From<ErrorImpl> for Error {
917 fn from(err: ErrorImpl) -> Self {
918 Self(err.into())
919 }
920}
921
922struct ErrorImpl {
923 kind: ErrorKind,
925
926 loc: &'static std::panic::Location<'static>,
928
929 path: Path,
931
932 span: Span,
934
935 token: Option<Token>,
937}
938
939impl fmt::Debug for ErrorImpl {
940 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
941 f.debug_struct("Error")
942 .field("kind", &self.kind)
943 .field("loc", &self.loc)
944 .field("path", &self.path)
945 .field("span", &self.span)
946 .field("token", &self.token)
947 .finish()
948 }
949}
950
951impl Error {
952 pub fn kind(&self) -> &ErrorKind {
954 &self.0.kind
955 }
956
957 pub fn path(&self) -> &Path {
959 &self.0.path
960 }
961
962 pub fn span(&self) -> Span {
964 self.0.span
965 }
966
967 pub fn token(&self) -> Option<&Token> {
968 self.0.token.as_ref()
969 }
970
971 pub fn into_parts(self) -> (ErrorKind, Path, Span) {
973 let ErrorImpl {
974 kind,
975 loc: _,
976 path,
977 span,
978 token: _,
979 } = *self.0;
980 (kind, path, span)
981 }
982
983 pub fn into_report(self, json: &str) -> ErrorReport<'_> {
986 ErrorReport::from_error(self, json)
987 }
988}
989
990#[derive(Debug)]
993pub struct ErrorReport<'buf> {
994 error: Error,
996
997 json_context: &'buf str,
999
1000 expanded_json_context: &'buf str,
1003
1004 span_bounds: SpanBounds,
1006}
1007
1008impl<'buf> ErrorReport<'buf> {
1009 fn from_error(error: Error, json: &'buf str) -> Self {
1011 let span = error.span();
1012 debug!(?error, ?span, json, "from_error");
1013 let json_context = &json.get(span.start..span.end).unwrap_or(json);
1014
1015 let start = {
1016 let s = &json.get(0..span.start).unwrap_or_default();
1017 line_col(s)
1018 };
1019 let end = {
1020 let relative_end = line_col(json_context);
1021 let line = start.line.saturating_add(relative_end.line);
1022
1023 if start.line == line {
1024 LineCol {
1025 line,
1026 col: start.col.saturating_add(relative_end.col),
1027 }
1028 } else {
1029 LineCol {
1030 line,
1031 col: relative_end.col,
1032 }
1033 }
1034 };
1035 let (prev, next) = find_expanded_newlines(json, span.start);
1036 let expanded_json_context = &json.get(prev..next).unwrap_or(json_context);
1037
1038 let span_bounds = SpanBounds { start, end };
1039
1040 Self {
1041 error,
1042 json_context,
1043 expanded_json_context,
1044 span_bounds,
1045 }
1046 }
1047
1048 pub fn json_context(&self) -> &'buf str {
1050 self.json_context
1051 }
1052
1053 pub fn expand_json_context(&self) -> &'buf str {
1056 self.expanded_json_context
1057 }
1058
1059 pub fn span_bounds(&self) -> &SpanBounds {
1061 &self.span_bounds
1062 }
1063
1064 pub fn into_error(self) -> Error {
1066 self.error
1067 }
1068}
1069
1070fn find_expanded_newlines(json: &str, byte_index: usize) -> (usize, usize) {
1071 let pre = json.get(..byte_index).unwrap_or(json);
1072 let post = json.get(byte_index..).unwrap_or(json);
1073
1074 let mut bytes = pre.as_bytes().iter().rev();
1075 let prev = pre
1076 .len()
1077 .saturating_sub(bytes.position(|b| *b == b'\n').unwrap_or_default());
1078
1079 let mut bytes = post.as_bytes().iter();
1080 let next = bytes
1081 .position(|b| *b == b'\n')
1082 .map(|idx| idx.saturating_add(byte_index))
1083 .unwrap_or(prev.saturating_add(post.len()));
1084
1085 (prev, next)
1086}
1087
1088#[derive(Clone, Debug)]
1090pub struct SpanBounds {
1091 pub start: LineCol,
1093
1094 pub end: LineCol,
1096}
1097
1098#[derive(Clone, Debug)]
1100pub struct LineCol {
1101 pub line: u32,
1103
1104 pub col: u32,
1106}
1107
1108impl From<(u32, u32)> for LineCol {
1109 fn from(value: (u32, u32)) -> Self {
1110 Self {
1111 line: value.0,
1112 col: value.1,
1113 }
1114 }
1115}
1116
1117impl From<LineCol> for (u32, u32) {
1118 fn from(value: LineCol) -> Self {
1119 (value.line, value.col)
1120 }
1121}
1122
1123impl PartialEq<(u32, u32)> for LineCol {
1124 fn eq(&self, other: &(u32, u32)) -> bool {
1125 self.line == other.0 && self.col == other.1
1126 }
1127}
1128
1129impl fmt::Display for LineCol {
1130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1131 write!(f, "{}:{}", self.line, self.col)
1132 }
1133}
1134
1135pub fn line_col(s: &str) -> LineCol {
1139 let mut chars = s.chars().rev();
1140 let mut line = 0_u32;
1141 let mut col = 0_u32;
1142
1143 for c in chars.by_ref() {
1148 if c == '\n' {
1150 let Some(n) = line.checked_add(1) else {
1151 break;
1152 };
1153 line = n;
1154 break;
1155 }
1156 let Some(n) = col.checked_add(1) else {
1157 break;
1158 };
1159 col = n;
1160 }
1161
1162 for c in chars {
1164 if c == '\n' {
1165 let Some(n) = line.checked_add(1) else {
1166 break;
1167 };
1168 line = n;
1169 }
1170 }
1171
1172 LineCol { line, col }
1173}
1174
1175#[derive(Debug)]
1177pub struct PartialError {
1178 kind: ErrorKind,
1180
1181 loc: &'static std::panic::Location<'static>,
1183
1184 token: Option<Token>,
1186}
1187
1188trait PartialIntoError<T> {
1190 fn with_head(self, head: &PartialElement<'_>) -> Result<T, Error>;
1192
1193 fn with_root_path(self) -> Result<T, Error>;
1197}
1198
1199impl<T> PartialIntoError<T> for Result<T, PartialError> {
1200 fn with_head(self, head: &PartialElement<'_>) -> Result<T, Error> {
1201 match self {
1202 Ok(v) => Ok(v),
1203 Err(err) => Err(err.with_head(head)),
1204 }
1205 }
1206
1207 fn with_root_path(self) -> Result<T, Error> {
1208 match self {
1209 Ok(v) => Ok(v),
1210 Err(err) => Err(err.with_root_path()),
1211 }
1212 }
1213}
1214
1215impl PartialError {
1216 fn with_head(self, parent: &PartialElement<'_>) -> Error {
1218 let Self { loc, kind, token } = self;
1219 let span_end = token.map(|t| t.span.end).unwrap_or_default();
1220
1221 let (path, span) = if let Some(elem) = parent.elements.last() {
1222 (
1223 Path::from_node(Arc::clone(&elem.path_node)),
1224 Span {
1225 start: elem.span.start,
1226 end: span_end,
1227 },
1228 )
1229 } else {
1230 (
1231 Path::from_node(Arc::clone(&parent.path)),
1232 Span {
1233 start: parent.span_start,
1234 end: span_end,
1235 },
1236 )
1237 };
1238
1239 ErrorImpl {
1240 kind,
1241 loc,
1242 path,
1243 span,
1244 token,
1245 }
1246 .into()
1247 }
1248
1249 pub fn with_root_path(self) -> Error {
1253 let Self { loc, kind, token } = self;
1254 let (span_start, span_end) = match (&kind, token) {
1255 (ErrorKind::UnexpectedToken, Some(t)) => (t.span.start, t.span.end),
1256 (_, Some(t)) => (0, t.span.end),
1257 (_, None) => (0, 0),
1258 };
1259 ErrorImpl {
1260 loc,
1261 kind,
1262 path: Path::root(),
1263 span: Span {
1264 start: span_start,
1265 end: span_end,
1266 },
1267 token,
1268 }
1269 .into()
1270 }
1271}
1272
1273#[derive(Debug)]
1275pub enum ErrorKind {
1276 Internal(Box<dyn std::error::Error + Send + Sync + 'static>),
1278
1279 UnexpectedEOF,
1281
1282 UnexpectedToken,
1284}
1285
1286impl ErrorKind {
1287 #[track_caller]
1288 fn into_partial_error(self, token: Option<Token>) -> PartialError {
1289 PartialError {
1290 kind: self,
1291 loc: std::panic::Location::caller(),
1292 token,
1293 }
1294 }
1295
1296 #[track_caller]
1297 pub fn into_partial_error_without_token(self) -> PartialError {
1298 PartialError {
1299 kind: self,
1300 loc: std::panic::Location::caller(),
1301 token: None,
1302 }
1303 }
1304}
1305
1306impl std::error::Error for Error {}
1307
1308impl fmt::Display for Error {
1309 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1310 let ErrorImpl {
1311 kind,
1312 loc,
1313 path,
1314 span: _,
1315 token,
1316 } = &*self.0;
1317
1318 write!(
1319 f,
1320 "Error: code location: {loc}; while parsing element at `{path}`"
1321 )?;
1322
1323 if let Some(token) = token {
1324 write!(f, " token: `{}`", token.kind)?;
1325 }
1326
1327 match kind {
1328 ErrorKind::Internal(err) => write!(f, "Internal: {err}"),
1329 ErrorKind::UnexpectedEOF => f.write_str("Unexpected EOF"),
1330 ErrorKind::UnexpectedToken => write!(f, "unexpected token"),
1331 }
1332 }
1333}
1334
1335#[derive(Debug)]
1339enum InternalError {
1340 BufferSlice(Span),
1347
1348 BufferType,
1357
1358 FromInt(TryFromIntError),
1364
1365 StringWithoutQuotes,
1370
1371 RawStringFromInvalidToken,
1376}
1377
1378impl InternalError {
1379 #[track_caller]
1380 fn into_partial_error(self, token: Option<Token>) -> PartialError {
1381 ErrorKind::Internal(Box::new(self)).into_partial_error(token)
1382 }
1383}
1384
1385impl std::error::Error for InternalError {}
1386
1387impl From<TryFromIntError> for InternalError {
1393 fn from(err: TryFromIntError) -> Self {
1394 InternalError::FromInt(err)
1395 }
1396}
1397
1398impl From<InternalError> for Error {
1399 #[track_caller]
1400 fn from(err: InternalError) -> Self {
1401 ErrorImpl {
1402 kind: ErrorKind::Internal(Box::new(err)),
1403 loc: std::panic::Location::caller(),
1404 path: Path::root(),
1405 span: Span { start: 0, end: 0 },
1406 token: None,
1407 }
1408 .into()
1409 }
1410}
1411
1412impl fmt::Display for InternalError {
1413 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1414 match self {
1415 InternalError::BufferSlice(span) => {
1416 write!(f, "Slice into buffer failed; span: {span:?}")
1417 }
1418 InternalError::BufferType => write!(f, "The tokens buffer is not a `Span`"),
1419 InternalError::FromInt(err) => write!(f, "{err}"),
1420 InternalError::StringWithoutQuotes => {
1421 write!(f, "A String was parsed without surrounding double quotes.")
1422 }
1423
1424 InternalError::RawStringFromInvalidToken => {
1425 write!(
1426 f,
1427 "A `RawString` was created using a `Token` that's not a `String`"
1428 )
1429 }
1430 }
1431 }
1432}
1433
1434trait InternalErrorIntoPartial<T> {
1435 #[track_caller]
1436 fn into_partial_error<F>(self, f: F) -> Result<T, PartialError>
1437 where
1438 F: FnOnce() -> Token;
1439}
1440
1441impl<T> InternalErrorIntoPartial<T> for Result<T, InternalError> {
1442 fn into_partial_error<F>(self, f: F) -> Result<T, PartialError>
1443 where
1444 F: FnOnce() -> Token,
1445 {
1446 match self {
1447 Ok(v) => Ok(v),
1448 Err(err) => {
1449 let token = f();
1450 Err(err.into_partial_error(Some(token)))
1451 }
1452 }
1453 }
1454}
1455
1456fn element_span(token_end: &Token, start: usize) -> Span {
1458 Span {
1459 start,
1460 end: token_end.span.end,
1461 }
1462}
1463
1464#[track_caller]
1468fn token_str<'buf>(json: &'buf str, token: &Token) -> Result<&'buf str, PartialError> {
1469 let start = token.span.start;
1470 let end = token.span.end;
1471 let s = &json
1472 .get(start..end)
1473 .ok_or(InternalError::BufferSlice(Span { start, end }))
1474 .into_partial_error(|| *token)?;
1475 Ok(s)
1476}
1477
1478#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Default)]
1480pub struct RawStr<'buf> {
1481 source: &'buf str,
1483
1484 span: Span,
1486}
1487
1488impl Borrow<str> for RawStr<'_> {
1490 fn borrow(&self) -> &str {
1491 self.source
1492 }
1493}
1494
1495impl Borrow<str> for &RawStr<'_> {
1497 fn borrow(&self) -> &str {
1498 self.source
1499 }
1500}
1501
1502impl<'buf> RawStr<'buf> {
1503 pub(super) fn from_str(source: &'buf str, span: Span) -> Self {
1504 Self { source, span }
1505 }
1506
1507 #[track_caller]
1509 pub(super) fn from_quoted_str(
1510 s: &'buf str,
1511 token: Token,
1512 ) -> Result<RawStr<'buf>, PartialError> {
1513 const QUOTE: char = '"';
1514
1515 if token.kind != TokenType::String {
1516 return Err(InternalError::RawStringFromInvalidToken.into_partial_error(Some(token)));
1517 }
1518
1519 let (_, s) = s
1521 .split_once(QUOTE)
1522 .ok_or(InternalError::StringWithoutQuotes)
1523 .into_partial_error(|| token)?;
1524
1525 let (source, _) = s
1526 .rsplit_once(QUOTE)
1527 .ok_or(InternalError::StringWithoutQuotes)
1528 .into_partial_error(|| token)?;
1529
1530 Ok(Self {
1531 source,
1532 span: token.span,
1533 })
1534 }
1535
1536 pub(crate) fn as_raw(&self) -> &'buf str {
1538 self.source
1539 }
1540
1541 pub(crate) fn decode_escapes(
1543 &self,
1544 elem: &Element<'buf>,
1545 ) -> Caveat<Cow<'_, str>, decode::Warning> {
1546 unescape_str(self.source, elem)
1547 }
1548
1549 pub(crate) fn has_escapes(
1551 &self,
1552 elem: &Element<'buf>,
1553 ) -> Caveat<decode::PendingStr<'buf>, decode::Warning> {
1554 decode::analyze(self.source, elem)
1555 }
1556
1557 pub fn span(&self) -> Span {
1559 self.span
1560 }
1561}
1562
1563impl fmt::Display for RawStr<'_> {
1564 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1565 fmt::Display::fmt(self.source, f)
1566 }
1567}
1568
1569#[track_caller]
1570fn token_str_as_string(json: &str, token: Token) -> Result<RawStr<'_>, PartialError> {
1571 let s = token_str(json, &token)?;
1572 let raw = RawStr::from_quoted_str(s, token)?;
1573 Ok(raw)
1574}