Skip to main content

rsonpath_syntax/
error.rs

1//! Error types for the crate.
2//!
3//! The main error type is [`ParseError`], which contains
4//! all syntax errors encountered during parsing.
5// Dev note: the pretty-printing logic is split into the `display` and `style` submodules.
6// That logic is rather involved and needs to be kept manageable.
7// Any logic regarding constructing the errors from the parser or handling those errors by users
8// should be added in this main module, while anything relating to how the errors are printed goes
9// to the submodules.
10use crate::error::display::fmt_parse_error;
11use crate::{
12    num::error::{JsonFloatParseError, JsonIntParseError},
13    str::{self},
14};
15use std::fmt::{self, Display};
16use thiserror::Error;
17
18mod display;
19mod formatter;
20mod style;
21
22#[derive(Debug)]
23pub(crate) struct ParseErrorBuilder {
24    syntax_errors: Vec<SyntaxError>,
25}
26
27/// Errors raised by the query parser.
28#[derive(Debug, Error)]
29pub struct ParseError {
30    input: String,
31    inner: InnerParseError,
32}
33
34impl Display for ParseError {
35    #[inline]
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        fmt_parse_error(self, &display::empty_style(), f)
38    }
39}
40
41impl ParseError {
42    /// Returns whether the error was caused by exceeding the parser's nesting limit.
43    #[inline]
44    #[must_use]
45    pub fn is_nesting_limit_exceeded(&self) -> bool {
46        matches!(self.inner, InnerParseError::RecursionLimit(_))
47    }
48}
49
50#[derive(Debug)]
51enum InnerParseError {
52    Syntax(Vec<SyntaxError>),
53    RecursionLimit(usize),
54}
55
56impl ParseErrorBuilder {
57    pub(crate) fn new() -> Self {
58        Self { syntax_errors: vec![] }
59    }
60
61    pub(crate) fn add(&mut self, syntax_error: SyntaxError) {
62        self.syntax_errors.push(syntax_error)
63    }
64
65    pub(crate) fn add_many(&mut self, mut syntax_errors: Vec<SyntaxError>) {
66        self.syntax_errors.append(&mut syntax_errors)
67    }
68
69    pub(crate) fn is_empty(&self) -> bool {
70        self.syntax_errors.is_empty()
71    }
72
73    pub(crate) fn build(self, str: String) -> ParseError {
74        ParseError {
75            input: str,
76            inner: InnerParseError::Syntax(self.syntax_errors),
77        }
78    }
79
80    pub(crate) fn recursion_limit_exceeded(str: String, recursion_limit: usize) -> ParseError {
81        ParseError {
82            input: str,
83            inner: InnerParseError::RecursionLimit(recursion_limit),
84        }
85    }
86}
87
88#[derive(Debug, PartialEq, Eq, Clone)]
89pub(crate) struct SyntaxError {
90    /// Kind of the error.
91    kind: SyntaxErrorKind,
92    /// The byte index at which the error occurred, counting from the end of the input.
93    rev_idx: usize,
94    /// The number of characters that the parser recognized as invalid.
95    len: usize,
96}
97
98#[derive(Debug, PartialEq, Eq, Clone)]
99pub(crate) enum SyntaxErrorKind {
100    // Top-level errors.
101    DisallowedLeadingWhitespace,
102    DisallowedTrailingWhitespace,
103    MissingRootIdentifier,
104    // String/name parsing errors.
105    InvalidUnescapedCharacter,
106    InvalidEscapeSequence,
107    UnpairedHighSurrogate,
108    UnpairedLowSurrogate,
109    InvalidHexDigitInUnicodeEscape,
110    MissingClosingSingleQuote,
111    MissingClosingDoubleQuote,
112    // Segment errors.
113    InvalidSegmentStart,
114    InvalidSegmentAfterTwoPeriods,
115    EmptySelector,
116    InvalidSelector,
117    MissingSelectorSeparator,
118    MissingClosingBracket,
119    InvalidNameShorthandAfterOnePeriod,
120    // Number parsing errors.
121    NegativeZeroInteger,
122    LeadingZeros,
123    NumberParseError(JsonFloatParseError),
124    // Index selector.
125    IndexParseError(JsonIntParseError),
126    // Slice selector.
127    SliceStartParseError(JsonIntParseError),
128    SliceEndParseError(JsonIntParseError),
129    SliceStepParseError(JsonIntParseError),
130    // Filter selector.
131    MissingClosingParenthesis,
132    InvalidNegation,
133    MissingComparisonOperator,
134    InvalidComparisonOperator,
135    InvalidComparable,
136    NonSingularQueryInComparison,
137    InvalidFilter,
138}
139
140impl SyntaxError {
141    pub(crate) fn new(kind: SyntaxErrorKind, rev_idx: usize, len: usize) -> Self {
142        Self { kind, rev_idx, len }
143    }
144}
145
146#[derive(Debug)]
147pub(crate) enum InternalParseError<'a> {
148    SyntaxError(SyntaxError, &'a str),
149    SyntaxErrors(Vec<SyntaxError>, &'a str),
150    RecursionLimitExceeded,
151    NomError(nom::error::Error<&'a str>),
152}
153
154impl<'a> nom::error::ParseError<&'a str> for InternalParseError<'a> {
155    fn from_error_kind(input: &'a str, kind: nom::error::ErrorKind) -> Self {
156        Self::NomError(nom::error::Error::from_error_kind(input, kind))
157    }
158
159    fn append(input: &'a str, kind: nom::error::ErrorKind, other: Self) -> Self {
160        match other {
161            Self::NomError(e) => Self::NomError(nom::error::Error::append(input, kind, e)),
162            _ => other,
163        }
164    }
165}