1use std::fmt;
12
13#[derive(Debug, Clone, PartialEq)]
15pub enum ParseErrorKind {
16 Other(String),
19 UnknownExpression(String),
21 WrongArgCount {
23 op: String,
24 expected: String,
25 found: usize,
26 },
27 TypeMismatch { expected: String, found: String },
29 NotComparable { op: String, ty: String },
31 CannotCompare { lhs: String, rhs: String },
33 NotInterpolatable(String),
35 UnboundVariable(String),
37 Zoom(&'static str),
39 RequiresExactlyOneArg { op: String, found: usize },
41 ExpectedOneArgument,
43 ExpectedArgsOfType { sig: String, found: String },
45 MatchAtLeast4 { found: usize },
47 ArrayItemType,
49 ArrayLength,
51 BareObject,
53 EmptyArray,
55 ExpressionNameNotString { found: &'static str },
57 GlobalStateProperty { found: String },
59 AscendingStops { kind: String },
61 ExponentialBase,
63 CubicBezier,
65 CollatorOptions,
67 NumberFormatExclusive,
69 SliceFirstArg { found: String },
71 SearchNeedle { found: String },
73 BranchLabelsType,
75 BranchLabelsUnique,
77 BranchLabelsEmpty,
79 BranchLabelNotInteger,
81 BranchLabelTooLarge,
83 GeojsonPolygon { op: String },
85 LetBindingNameString,
87 VarBindingName,
89 NumberFormatOptionsObject,
91 VerticalAlign { found: String },
93 ExpectedEvenArgs { op: &'static str },
95 ExpectedOddArgsCase,
97 ExpectedOddArgsLet,
99 FormatAtLeastOne,
101 CollatorOneArg,
103 NumberFormatTwoArgs,
105 ExpectedNArgs { n: usize, found: usize },
107 FormatFirstSection,
109 ExtArgCount {
111 kind: &'static str,
112 op: String,
113 expected: usize,
114 found: usize,
115 },
116 MacroDepth { op: String },
118 InterpolationStopNumber,
120 StepStopNumber,
122 InterpolationTypeArray,
124 InterpolationTypeName,
126 UnknownInterpolationType { name: String },
128 CollatorNonString,
130 ExpectedStringOrArray { found: String },
132 FormattedTextType,
134 VariableName,
136}
137
138impl fmt::Display for ParseErrorKind {
139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 match self {
141 ParseErrorKind::Other(s) => write!(f, "{s}"),
142 ParseErrorKind::UnknownExpression(op) => write!(
143 f,
144 "Unknown expression \"{op}\". If you wanted a literal array, use [\"literal\", [...]]."
145 ),
146 ParseErrorKind::WrongArgCount {
147 op,
148 expected,
149 found,
150 } => {
151 let _ = op;
152 write!(f, "Expected {expected}, but found {found} instead.")
153 }
154 ParseErrorKind::TypeMismatch { expected, found } => {
155 write!(f, "Expected {expected} but found {found} instead.")
156 }
157 ParseErrorKind::NotComparable { op, ty } => {
158 write!(f, "\"{op}\" comparisons are not supported for type '{ty}'.")
159 }
160 ParseErrorKind::CannotCompare { lhs, rhs } => {
161 write!(f, "Cannot compare types '{lhs}' and '{rhs}'.")
162 }
163 ParseErrorKind::NotInterpolatable(ty) => write!(f, "Type {ty} is not interpolatable."),
164 ParseErrorKind::UnboundVariable(name) => write!(
165 f,
166 "Unknown variable \"{name}\". Make sure \"{name}\" has been bound in an enclosing \"let\" expression before using it."
167 ),
168 ParseErrorKind::Zoom(msg) => write!(f, "{msg}"),
169 ParseErrorKind::RequiresExactlyOneArg { op, found } => write!(
170 f,
171 "'{op}' expression requires exactly one argument, but found {found} instead."
172 ),
173 ParseErrorKind::ExpectedOneArgument => write!(f, "Expected one argument."),
174 ParseErrorKind::ExpectedArgsOfType { sig, found } => write!(
175 f,
176 "Expected arguments of type {sig}, but found ({found}) instead."
177 ),
178 ParseErrorKind::MatchAtLeast4 { found } => {
179 write!(f, "Expected at least 4 arguments, but found only {found}.")
180 }
181 ParseErrorKind::ArrayItemType => write!(
182 f,
183 "The item type argument of \"array\" must be one of string, number, boolean"
184 ),
185 ParseErrorKind::ArrayLength => write!(
186 f,
187 "The length argument to \"array\" must be a positive integer literal"
188 ),
189 ParseErrorKind::BareObject => {
190 write!(f, "Bare objects invalid. Use [\"literal\", {{...}}] instead.")
191 }
192 ParseErrorKind::EmptyArray => write!(
193 f,
194 "Expected an array with at least one element. If you wanted a literal array, use [\"literal\", []]."
195 ),
196 ParseErrorKind::ExpressionNameNotString { found } => write!(
197 f,
198 "Expression name must be a string, but found {found} instead. If you wanted a literal array, use [\"literal\", [...]]."
199 ),
200 ParseErrorKind::GlobalStateProperty { found } => {
201 write!(f, "Global state property must be string, but found {found} instead.")
202 }
203 ParseErrorKind::AscendingStops { kind } => write!(
204 f,
205 "Input/output pairs for \"{kind}\" expressions must be arranged with input values in strictly ascending order."
206 ),
207 ParseErrorKind::ExponentialBase => {
208 write!(f, "Exponential interpolation requires a numeric base.")
209 }
210 ParseErrorKind::CubicBezier => write!(
211 f,
212 "Cubic bezier interpolation requires four numeric arguments with values between 0 and 1."
213 ),
214 ParseErrorKind::CollatorOptions => {
215 write!(f, "Collator options argument must be an object.")
216 }
217 ParseErrorKind::NumberFormatExclusive => write!(
218 f,
219 "NumberFormat options `currency` and `unit` are mutually exclusive"
220 ),
221 ParseErrorKind::SliceFirstArg { found } => write!(
222 f,
223 "Expected first argument to be of type array or string, but found {found} instead"
224 ),
225 ParseErrorKind::SearchNeedle { found } => write!(
226 f,
227 "Expected first argument to be of type boolean, string, number or null, but found {found} instead"
228 ),
229 ParseErrorKind::BranchLabelsType => {
230 write!(f, "Branch labels must be numbers or strings.")
231 }
232 ParseErrorKind::BranchLabelsUnique => write!(f, "Branch labels must be unique."),
233 ParseErrorKind::BranchLabelsEmpty => write!(f, "Expected at least one branch label."),
234 ParseErrorKind::BranchLabelNotInteger => {
235 write!(f, "Numeric branch labels must be integer values.")
236 }
237 ParseErrorKind::BranchLabelTooLarge => write!(
238 f,
239 "Branch labels must be integers no larger than 9007199254740991."
240 ),
241 ParseErrorKind::GeojsonPolygon { op } => write!(
242 f,
243 "'{op}' expression requires valid geojson object that contains polygon geometry type."
244 ),
245 ParseErrorKind::LetBindingNameString => {
246 write!(f, "'let' binding names must be strings.")
247 }
248 ParseErrorKind::VarBindingName => write!(f, "'var' requires a string binding name."),
249 ParseErrorKind::NumberFormatOptionsObject => {
250 write!(f, "'number-format' options must be an object.")
251 }
252 ParseErrorKind::VerticalAlign { found } => write!(
253 f,
254 "'vertical-align' must be one of: 'bottom', 'center', 'top' but found '{found}' instead."
255 ),
256 ParseErrorKind::ExpectedEvenArgs { op } => {
257 write!(f, "Expected an even number of arguments (>= 4) to '{op}'.")
258 }
259 ParseErrorKind::ExpectedOddArgsCase => {
260 write!(f, "Expected an odd number of arguments (>= 3) to 'case'.")
261 }
262 ParseErrorKind::ExpectedOddArgsLet => {
263 write!(f, "Expected an odd number of arguments to 'let'.")
264 }
265 ParseErrorKind::FormatAtLeastOne => {
266 write!(f, "Expected at least one argument to 'format'.")
267 }
268 ParseErrorKind::CollatorOneArg => write!(f, "Expected one argument to 'collator'."),
269 ParseErrorKind::NumberFormatTwoArgs => {
270 write!(f, "Expected two arguments to 'number-format'.")
271 }
272 ParseErrorKind::ExpectedNArgs { n, found } => {
273 write!(f, "Expected {n} arguments, but found {found} instead.")
274 }
275 ParseErrorKind::FormatFirstSection => {
276 write!(f, "First argument to 'format' must be an image or text section.")
277 }
278 ParseErrorKind::ExtArgCount {
279 kind,
280 op,
281 expected,
282 found,
283 } => write!(f, "{kind} '{op}' expects {expected} argument(s), found {found}."),
284 ParseErrorKind::MacroDepth { op } => {
285 write!(f, "Macro expansion too deep expanding '{op}' (recursive macro?).")
286 }
287 ParseErrorKind::InterpolationStopNumber => {
288 write!(f, "Interpolation stop inputs must be numbers.")
289 }
290 ParseErrorKind::StepStopNumber => write!(f, "Step stop inputs must be numbers."),
291 ParseErrorKind::InterpolationTypeArray => {
292 write!(f, "Interpolation type must be an array, e.g. [\"linear\"].")
293 }
294 ParseErrorKind::InterpolationTypeName => {
295 write!(f, "Interpolation type name must be a string.")
296 }
297 ParseErrorKind::UnknownInterpolationType { name } => {
298 write!(f, "Unknown interpolation type \"{name}\".")
299 }
300 ParseErrorKind::CollatorNonString => {
301 write!(f, "Cannot use collator to compare non-string types.")
302 }
303 ParseErrorKind::ExpectedStringOrArray { found } => write!(
304 f,
305 "Expected argument of type string or array, but found {found} instead."
306 ),
307 ParseErrorKind::FormattedTextType => write!(
308 f,
309 "Formatted text type must be 'string', 'value', 'image' or 'null'."
310 ),
311 ParseErrorKind::VariableName => write!(
312 f,
313 "Variable names must contain only alphanumeric characters or '_'."
314 ),
315 }
316 }
317}
318
319#[derive(Debug, Clone, PartialEq)]
323pub struct ParseError {
324 pub kind: ParseErrorKind,
325 pub key: String,
327}
328
329impl ParseError {
330 pub fn of(kind: ParseErrorKind) -> ParseError {
332 ParseError {
333 kind,
334 key: String::new(),
335 }
336 }
337
338 pub fn new(message: impl Into<String>) -> ParseError {
340 ParseError::of(ParseErrorKind::Other(message.into()))
341 }
342
343 pub(crate) fn at(mut self, index: usize) -> ParseError {
345 self.key = format!("[{index}]{}", self.key);
346 self
347 }
348}
349
350impl fmt::Display for ParseError {
351 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
352 write!(f, "{}", self.kind)
353 }
354}
355
356impl std::error::Error for ParseError {}
357
358#[derive(Debug, Clone, PartialEq)]
360pub enum EvalErrorKind {
361 Other(String),
364 TypeMismatch { expected: String, found: String },
366 TypeMismatchArg {
369 arg: &'static str,
370 expected: String,
371 found: String,
372 },
373 CouldNotParse { ty: &'static str, value: String },
376 CouldNotConvertToNumber { value: String },
378 ArrayIndexNegative { index: f64 },
380 ArrayIndexOutOfBounds { index: f64, max: usize },
382 ArrayIndexNotInteger { index: f64 },
384 InvalidRgba { value: String, reason: &'static str },
387 NotOrderedComparable {
389 op: String,
390 lhs: String,
391 rhs: String,
392 },
393 SearchNeedle { found: String },
395 InterpolationOutputs,
397 MaxCallDepth { op: String },
399 ZoomUnavailable,
401 Unimplemented { op: String },
403 UnknownVariable { name: String },
405}
406
407impl fmt::Display for EvalErrorKind {
408 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409 match self {
410 EvalErrorKind::Other(s) => write!(f, "{s}"),
411 EvalErrorKind::TypeMismatch { expected, found } => write!(
412 f,
413 "Expected value to be of type {expected}, but found {found} instead."
414 ),
415 EvalErrorKind::TypeMismatchArg {
416 arg,
417 expected,
418 found,
419 } => write!(
420 f,
421 "Expected {arg} to be of type {expected}, but found {found} instead."
422 ),
423 EvalErrorKind::CouldNotParse { ty, value } => {
424 write!(f, "Could not parse {ty} from value '{value}'")
425 }
426 EvalErrorKind::CouldNotConvertToNumber { value } => {
427 write!(f, "Could not convert {value} to number.")
428 }
429 EvalErrorKind::ArrayIndexNegative { index } => {
430 write!(f, "Array index out of bounds: {index} < 0.")
431 }
432 EvalErrorKind::ArrayIndexOutOfBounds { index, max } => {
433 write!(f, "Array index out of bounds: {index} > {max}.")
434 }
435 EvalErrorKind::ArrayIndexNotInteger { index } => {
436 write!(f, "Array index must be an integer, but found {index} instead.")
437 }
438 EvalErrorKind::InvalidRgba { value, reason } => {
439 write!(f, "Invalid rgba value {value}: {reason}")
440 }
441 EvalErrorKind::NotOrderedComparable { op, lhs, rhs } => write!(
442 f,
443 "Expected arguments for \"{op}\" to be (string, string) or (number, number), but found ({lhs}, {rhs}) instead."
444 ),
445 EvalErrorKind::SearchNeedle { found } => write!(
446 f,
447 "Expected first argument to be of type boolean, string, number or null, but found {found} instead."
448 ),
449 EvalErrorKind::InterpolationOutputs => write!(
450 f,
451 "Interpolation outputs must be numbers, colors, or arrays of numbers."
452 ),
453 EvalErrorKind::MaxCallDepth { op } => {
454 write!(f, "Maximum call depth exceeded calling function '{op}'.")
455 }
456 EvalErrorKind::ZoomUnavailable => {
457 write!(f, "The 'zoom' expression is unavailable here.")
458 }
459 EvalErrorKind::Unimplemented { op } => write!(f, "Unimplemented operator \"{op}\"."),
460 EvalErrorKind::UnknownVariable { name } => write!(f, "Unknown variable \"{name}\"."),
461 }
462 }
463}
464
465#[derive(Debug, Clone, PartialEq)]
469pub struct EvalError {
470 pub kind: EvalErrorKind,
471}
472
473impl EvalError {
474 pub fn of(kind: EvalErrorKind) -> EvalError {
475 EvalError { kind }
476 }
477
478 pub fn new(message: impl Into<String>) -> EvalError {
479 EvalError::of(EvalErrorKind::Other(message.into()))
480 }
481}
482
483impl fmt::Display for EvalError {
484 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
485 write!(f, "{}", self.kind)
486 }
487}
488
489impl std::error::Error for EvalError {}