/rust/registry/src/index.crates.io-1949cf8c6b5b557f/jsonc-parser-0.34.0/src/errors.rs
Line | Count | Source |
1 | | use std::fmt; |
2 | | |
3 | | use crate::ParseStringErrorKind; |
4 | | |
5 | | use super::common::Range; |
6 | | |
7 | | #[derive(Debug)] |
8 | | pub enum ParseErrorKind { |
9 | | BareDecimalPointNumbersNotAllowed, |
10 | | CommentsNotAllowed, |
11 | | ExpectedColonAfterObjectKey, |
12 | | ExpectedObjectValue, |
13 | | ExpectedDigit, |
14 | | ExpectedDigitFollowingNegativeSign, |
15 | | ExpectedPlusMinusOrDigitInNumberLiteral, |
16 | | ExpectedStringObjectProperty, |
17 | | HexadecimalNumbersNotAllowed, |
18 | | ExpectedComma, |
19 | | MultipleRootJsonValues, |
20 | | NonFiniteNumbersNotAllowed, |
21 | | SingleQuotedStringsNotAllowed, |
22 | | String(ParseStringErrorKind), |
23 | | TrailingCommasNotAllowed, |
24 | | UnaryPlusNumbersNotAllowed, |
25 | | UnexpectedCloseBrace, |
26 | | UnexpectedCloseBracket, |
27 | | UnexpectedColon, |
28 | | UnexpectedComma, |
29 | | UnexpectedToken, |
30 | | UnexpectedTokenInObject, |
31 | | UnexpectedWord, |
32 | | UnterminatedArray, |
33 | | UnterminatedCommentBlock, |
34 | | UnterminatedObject, |
35 | | NestingDepthExceeded, |
36 | | /// Custom error message, used by the serde deserializer. |
37 | | #[cfg(feature = "serde")] |
38 | | Custom(String), |
39 | | } |
40 | | |
41 | | impl std::fmt::Display for ParseErrorKind { |
42 | 0 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
43 | | use ParseErrorKind::*; |
44 | 0 | match self { |
45 | | BareDecimalPointNumbersNotAllowed => { |
46 | 0 | write!(f, "Leading or trailing decimal points on numbers are not allowed") |
47 | | } |
48 | | CommentsNotAllowed => { |
49 | 0 | write!(f, "Comments are not allowed") |
50 | | } |
51 | | ExpectedColonAfterObjectKey => { |
52 | 0 | write!(f, "Expected colon after the string or word in object property") |
53 | | } |
54 | | ExpectedDigit => { |
55 | 0 | write!(f, "Expected digit") |
56 | | } |
57 | | ExpectedDigitFollowingNegativeSign => { |
58 | 0 | write!(f, "Expected digit following negative sign") |
59 | | } |
60 | | ExpectedPlusMinusOrDigitInNumberLiteral => { |
61 | 0 | write!(f, "Expected plus, minus, or digit in number literal") |
62 | | } |
63 | | ExpectedObjectValue => { |
64 | 0 | write!(f, "Expected value after colon in object property") |
65 | | } |
66 | | ExpectedStringObjectProperty => { |
67 | 0 | write!(f, "Expected string for object property") |
68 | | } |
69 | | HexadecimalNumbersNotAllowed => { |
70 | 0 | write!(f, "Hexadecimal numbers are not allowed") |
71 | | } |
72 | | ExpectedComma => { |
73 | 0 | write!(f, "Expected comma") |
74 | | } |
75 | | MultipleRootJsonValues => { |
76 | 0 | write!(f, "Text cannot contain more than one JSON value") |
77 | | } |
78 | | NonFiniteNumbersNotAllowed => { |
79 | 0 | write!(f, "Infinity and NaN are not allowed") |
80 | | } |
81 | | SingleQuotedStringsNotAllowed => { |
82 | 0 | write!(f, "Single-quoted strings are not allowed") |
83 | | } |
84 | 0 | String(kind) => kind.fmt(f), |
85 | | TrailingCommasNotAllowed => { |
86 | 0 | write!(f, "Trailing commas are not allowed") |
87 | | } |
88 | | UnaryPlusNumbersNotAllowed => { |
89 | 0 | write!(f, "Unary plus on numbers is not allowed") |
90 | | } |
91 | | UnexpectedCloseBrace => { |
92 | 0 | write!(f, "Unexpected close brace") |
93 | | } |
94 | | UnexpectedCloseBracket => { |
95 | 0 | write!(f, "Unexpected close bracket") |
96 | | } |
97 | | UnexpectedColon => { |
98 | 0 | write!(f, "Unexpected colon") |
99 | | } |
100 | | UnexpectedComma => { |
101 | 0 | write!(f, "Unexpected comma") |
102 | | } |
103 | | UnexpectedWord => { |
104 | 0 | write!(f, "Unexpected word") |
105 | | } |
106 | | UnexpectedToken => { |
107 | 0 | write!(f, "Unexpected token") |
108 | | } |
109 | | UnexpectedTokenInObject => { |
110 | 0 | write!(f, "Unexpected token in object") |
111 | | } |
112 | | UnterminatedArray => { |
113 | 0 | write!(f, "Unterminated array") |
114 | | } |
115 | | UnterminatedCommentBlock => { |
116 | 0 | write!(f, "Unterminated comment block") |
117 | | } |
118 | | UnterminatedObject => { |
119 | 0 | write!(f, "Unterminated object") |
120 | | } |
121 | | NestingDepthExceeded => { |
122 | 0 | write!(f, "Maximum nesting depth exceeded") |
123 | | } |
124 | | #[cfg(feature = "serde")] |
125 | 0 | Custom(msg) => write!(f, "{}", msg), |
126 | | } |
127 | 0 | } |
128 | | } |
129 | | |
130 | | #[derive(Debug)] |
131 | | struct ParseErrorInner { |
132 | | range: Range, |
133 | | line_display: usize, |
134 | | column_display: usize, |
135 | | kind: ParseErrorKind, |
136 | | } |
137 | | |
138 | | /// Error that could occur while parsing or tokenizing. |
139 | | #[derive(Debug)] |
140 | | pub struct ParseError(Box<ParseErrorInner>); |
141 | | |
142 | | impl std::error::Error for ParseError {} |
143 | | |
144 | | impl ParseError { |
145 | 4.07k | pub(crate) fn new(range: Range, kind: ParseErrorKind, file_text: &str) -> ParseError { |
146 | 4.07k | let (line_display, column_display) = get_line_and_column_display(range, file_text); |
147 | 4.07k | ParseError(Box::new(ParseErrorInner { |
148 | 4.07k | range, |
149 | 4.07k | line_display, |
150 | 4.07k | column_display, |
151 | 4.07k | kind, |
152 | 4.07k | })) |
153 | 4.07k | } |
154 | | |
155 | | /// Start and end position of the error. |
156 | 0 | pub fn range(&self) -> Range { |
157 | 0 | self.0.range |
158 | 0 | } |
159 | | |
160 | | /// 1-indexed line number the error occurred on. |
161 | 0 | pub fn line_display(&self) -> usize { |
162 | 0 | self.0.line_display |
163 | 0 | } |
164 | | |
165 | | /// 1-indexed column number the error occurred on. |
166 | | /// |
167 | | /// Note: Use the `error_unicode_width` feature to get the correct column |
168 | | /// number for Unicode characters on the line, otherwise this is just the |
169 | | /// number of characters by default. |
170 | 0 | pub fn column_display(&self) -> usize { |
171 | 0 | self.0.column_display |
172 | 0 | } |
173 | | |
174 | | /// Error message. |
175 | 0 | pub fn kind(&self) -> &ParseErrorKind { |
176 | 0 | &self.0.kind |
177 | 0 | } |
178 | | |
179 | | /// Creates an error with a custom message and no position info. |
180 | | #[cfg(feature = "serde")] |
181 | 8.08k | pub(crate) fn custom_err(msg: String) -> ParseError { |
182 | 8.08k | ParseError(Box::new(ParseErrorInner { |
183 | 8.08k | range: Range { start: 0, end: 0 }, |
184 | 8.08k | line_display: 1, |
185 | 8.08k | column_display: 1, |
186 | 8.08k | kind: ParseErrorKind::Custom(msg), |
187 | 8.08k | })) |
188 | 8.08k | } |
189 | | |
190 | | /// Attaches position info to an error that doesn't have any yet. |
191 | | #[cfg(feature = "serde")] |
192 | 24.1k | pub(crate) fn with_position(mut self, range: Range, file_text: &str) -> ParseError { |
193 | 24.1k | if self.0.range.start == 0 && self.0.range.end == 0 { |
194 | 5.25k | let (line_display, column_display) = get_line_and_column_display(range, file_text); |
195 | 5.25k | self.0.range = range; |
196 | 5.25k | self.0.line_display = line_display; |
197 | 5.25k | self.0.column_display = column_display; |
198 | 18.9k | } |
199 | 24.1k | self |
200 | 24.1k | } |
201 | | } |
202 | | |
203 | | impl fmt::Display for ParseError { |
204 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
205 | 0 | let inner = &*self.0; |
206 | 0 | write!( |
207 | 0 | f, |
208 | | "{} on line {} column {}", |
209 | | inner.kind, inner.line_display, inner.column_display |
210 | | ) |
211 | 0 | } |
212 | | } |
213 | | |
214 | 9.32k | fn get_line_and_column_display(range: Range, file_text: &str) -> (usize, usize) { |
215 | 9.32k | let mut line_index = 0; |
216 | 9.32k | let mut column_index = 0; |
217 | 16.6M | for (i, c) in file_text[..range.start].char_indices() { |
218 | | // a lone \r ends a line comment, so it also counts as a line break here |
219 | 16.6M | if c == '\n' || c == '\r' && file_text.as_bytes().get(i + 1) != Some(&b'\n') { |
220 | 67.8k | line_index += 1; |
221 | 67.8k | column_index = 0; |
222 | 67.8k | } else { |
223 | | #[cfg(feature = "error_unicode_width")] |
224 | | { |
225 | | if let Some(width) = unicode_width::UnicodeWidthChar::width_cjk(c) { |
226 | | column_index += width; |
227 | | } |
228 | | } |
229 | | #[cfg(not(feature = "error_unicode_width"))] |
230 | 16.5M | { |
231 | 16.5M | column_index += 1; |
232 | 16.5M | } |
233 | | } |
234 | | } |
235 | 9.32k | (line_index + 1, column_index + 1) |
236 | 9.32k | } |