xee_interpreter/
error.rs

1use ibig::error::OutOfBoundsError;
2use strum::EnumMessage;
3use strum_macros::{Display, EnumMessage};
4use xee_xpath_ast::ParserError;
5use xot::xmlname::NameStrInfo;
6
7use crate::span::SourceSpan;
8
9/// An error code with an optional source span.
10///
11/// Also known as `SpannedError` internally.
12#[derive(Debug, PartialEq)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize))]
14pub struct SpannedError {
15    /// The error code
16    pub error: Error,
17    /// The source span where the error occurred
18    pub span: Option<SourceSpan>,
19}
20
21/// XPath/XSLT error code
22///
23/// These are specified by the XPath and XSLT specifications.
24///
25/// Xee extends them with a few additional error codes.
26///
27/// Also known as `Error` internally.
28#[derive(Debug, Clone, PartialEq, Display, EnumMessage)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize))]
30pub enum Error {
31    /// Stack overflow.
32    ///
33    /// Internal stack overflow.
34    StackOverflow,
35
36    /// Unsupported XPath feature.
37    ///
38    /// This XPath feature is not supported by Xee.
39    Unsupported,
40
41    /// Used query with wrong queries.
42    ///
43    /// The query was created with a different queries collection.
44    UsedQueryWithWrongQueries,
45
46    // XPath error conditions: https://www.w3.org/TR/xpath-31/#id-errors
47    /// Component absent in static context.
48    ///  
49    /// It is a static error if analysis of an expression relies on some
50    /// component of the static context that is absent.
51    XPST0001,
52    /// Component absent in dynamic context.
53    ///
54    /// It is a dynamic error if evaluation of an expression relies on some
55    /// part of the dynamic context that is absent.
56    XPDY0002,
57    /// Parse error.
58    ///
59    /// It is a static error if an expression is not a valid instance of the
60    /// grammar defined in A.1 EBNF.
61    XPST0003,
62    /// Type error.
63    ///
64    /// It is a type error if, during the static analysis phase, an expression
65    /// is found to have a static type that is not appropriate for the context
66    /// in which the expression occurs, or during the dynamic evaluation phase,
67    /// the dynamic type of a value does not match a required type as specified
68    /// by the matching rules in 2.5.5 SequenceType Matching.
69    XPTY0004,
70    /// Empty Sequence type error.
71    ///
72    /// During the analysis phase, it is a static error if the static type
73    /// assigned to an expression other than the expression `()` or `data(())`
74    /// is `empty-sequence()`.
75    XPST0005,
76    /// Name not defined.
77    ///
78    /// It is a static error if an expression refers to an element name,
79    /// attribute name, schema type name, namespace prefix, or variable name
80    /// that is not defined in the static context, except for an ElementName in
81    /// an ElementTest or an AttributeName in an AttributeTest.
82    XPST0008,
83    /// Namespace axis not supported.
84    ///
85    /// An implementation that does not support the namespace axis must raise a
86    /// static error if it encounters a reference to the namespace axis and
87    /// XPath 1.0 compatibility mode is false.
88    XPST0010,
89    /// Type error: incorrect function name or number of arguments.
90    ///
91    /// It is a static error if the expanded QName and number of arguments in a
92    /// static function call do not match the name and arity of a function
93    /// signature in the static context.
94    XPST0017,
95    /// Type error: inconsistent sequence.
96    ///
97    /// It is a type error if the result of a path operator contains both nodes
98    /// and non-nodes.
99    XPTY0018,
100    /// Type error: path operator must be applied to node sequence
101    ///
102    /// It is a type error if E1 in a path expression E1/E2 does not evaluate to a
103    /// sequence of nodes.
104    XPTY0019,
105    /// Type error: context item is not a node in an axis step.
106    ///
107    /// It is a type error if, in an axis step, the context item is not a node.
108    XPTY0020,
109    /// Multiple parameters with same name.
110    ///
111    /// It is a static error for an inline function expression to have more
112    /// than one parameter with the same name.
113    XQST0039,
114    /// Invalid Braced URI Literal.
115    ///
116    /// An implementation MAY raise a static error if the value of a
117    /// BracedURILiteral is of nonzero length and is neither an absolute URI
118    /// nor a relative URI.
119    XQST0046,
120    /// Treat type does not match sequence type.
121    ///
122    /// It is a dynamic error if the dynamic type of the operand of a treat
123    /// expression does not match the sequence type specified by the treat
124    /// expression. This error might also be raised by a path expression
125    /// beginning with "/" or "//" if the context node is not in a tree that is
126    /// rooted at a document node. This is because a leading "/" or "//" in a
127    /// path expression is an abbreviation for an initial step that includes
128    /// the clause `treat as document-node()`.
129    XPDY0050,
130    /// Undefined type reference
131    ///
132    /// It is a static error if the expanded QName for an AtomicOrUnionType in
133    /// a SequenceType is not defined in the in-scope schema types as a
134    /// generalized atomic type.
135    XPST0051,
136    /// Invalid type named in cast or castable expression.
137    ///
138    /// The type named in a cast or castable expression must be the name of a
139    /// type defined in the in-scope schema types, and the type must be simple.
140    XQST0052,
141    /// Illegal prefix
142    ///
143    /// A static error is raised if any of the following conditions is
144    /// statically detected in any expression:
145    ///
146    /// - The prefix xml is bound to some namespace URI other than
147    ///   `http://www.w3.org/XML/1998/namespace`.
148    /// - A prefix other than xml is bound to the namespace URI
149    ///   `http://www.w3.org/XML/1998/namespace`.
150    /// - The prefix xmlns is bound to any namespace URI.
151    /// - A prefix other than xmlns is bound to the namespace URI
152    ///   `http://www.w3.org/2000/xmlns/`.
153    XQST0070,
154    /// Invalid target type of cast or castable expression.
155    ///
156    /// It is a static error if the target type of a cast or castable
157    /// expression is xs:NOTATION, xs:anySimpleType, or xs:anyAtomicType.
158    XPST0080,
159    /// Unknown namespace prefix.
160    ///
161    /// It is a static error if a QName used in an expression contains a
162    /// namespace prefix that cannot be expanded into a namespace URI by using
163    /// the statically known namespaces.
164    XPST0081,
165    /// Type error: namespace-sensitive type expected.
166    ///
167    /// When applying the function conversion rules, if an item is of type
168    /// xs:untypedAtomic and the expected type is namespace-sensitive, a type
169    /// error is raised.
170    XPTY0117,
171    /// Implementation-dependent limit exceeded.
172    ///
173    /// An implementation-dependent limit has been exceeded.
174    XPDY0130,
175    /// Namespace axis not supported.
176    ///
177    /// The namespace axis is not supported.
178    XQST0134,
179    /// Duplicate key values in a map.
180    ///
181    /// No two keys in a map may have the same key value.
182    XQDY0137,
183    // XPath errors and functions: https://www.w3.org/TR/xpath-functions-31/#error-summary
184    /// Wrong number of arguments.
185    ///
186    /// Raised when fn:apply is called and the arity of the supplied function
187    /// is not the same as the number of members in the supplied array.
188    FOAP0001,
189    /// Division by zero.
190    ///
191    /// This error is raised whenever an attempt is made to divide by zero.
192    FOAR0001,
193    /// Numeric operation overflow/underflow.
194    ///
195    /// This error is raised whenever numeric operations result in an overflow or underflow.
196    FOAR0002,
197    /// Array index out of bounds.
198    ///
199    /// This error is raised when an integer used to select a member of an array is outside the range of values for that array.
200    FOAY0001,
201    /// Negative array length.
202    ///
203    /// This error is raised when the $length argument to array:subarray is negative.
204    FOAY0002,
205    /// Input value too large for decimal.
206    ///
207    /// Raised when casting to xs:decimal if the supplied value exceeds the implementation-defined limits for the datatype.
208    FOCA0001,
209    /// Invalid lexical value.
210    ///
211    /// Raised by fn:resolve-QName and fn:QName when a supplied value does not
212    /// have the lexical form of a QName or URI respectively; and when casting
213    /// to decimal, if the supplied value is NaN or Infinity.
214    FOCA0002,
215    /// Input too large for integer.
216    ///
217    /// Raised when casting to xs:integer if the supplied value exceeds the implementation-defined limits for the datatype.
218    FOCA0003,
219    /// NaN supplied as float/double value.
220    ///
221    /// Raised when multiplying or dividing a duration by a number, if the
222    /// number supplied is NaN.
223    FOCA0005,
224    /// String to be cast to decimal has too many digits of precision.
225    ///
226    /// Raised when casting a string to xs:decimal if the string has more
227    /// digits of precision than the implementation can represent (the
228    /// implementation also has the option of rounding).
229    FOCA0006,
230    /// Codepoint not valid.
231    ///
232    /// Raised by fn:codepoints-to-string if the input contains an integer that is not the codepoint of a valid XML character.
233    FOCH0001,
234    /// Unsupported collation.
235    ///
236    /// Raised by any function that uses a collation if the requested collation
237    /// is not recognized.
238    FOCH0002,
239    /// Unsupported normalization form.
240    ///
241    /// Raised by fn:normalize-unicode if the requested normalization form is
242    /// not supported by the implementation.
243    FOCH0003,
244    /// Collation does not support collation units.
245    ///
246    /// Raised by functions such as fn:contains if the requested collation does
247    /// not operate on a character-by-character basis.
248    FOCH0004,
249    /// No context document.
250    ///
251    /// Raised by fn:id, fn:idref, and fn:element-with-id if the node that
252    /// identifies the tree to be searched is a node in a tree whose root is
253    /// not a document node.
254    FODC0001,
255    /// Error retrieving resource.
256    ///
257    /// Raised by fn:doc, fn:collection, and fn:uri-collection to indicate that
258    /// either the supplied URI cannot be dereferenced to obtain a resource, or
259    /// the resource that is returned is not parseable as XML.
260    FODC0002,
261    /// Function not defined as deterministic.
262    ///
263    /// Raised by fn:doc, fn:collection, and fn:uri-collection to indicate that
264    /// it is not possible to return a result that is guaranteed deterministic.
265    FODC0003,
266    /// Invalid collection URI.
267    ///
268    /// Raised by fn:collection and fn:uri-collection if the argument is not
269    /// a valid xs:anyURI.
270    FODC0004,
271    /// Invalid argument to fn:doc or fn:doc-available.
272    ///
273    /// Raised (optionally) by fn:doc and fn:doc-available if the argument is
274    /// not a valid URI reference.
275    FODC0005,
276    /// String passed to fn:parse-xml is not a well-formed XML document.
277    ///
278    /// Raised by fn:parse-xml if the supplied string is not a well-formed and
279    /// namespace-well-formed XML document; or if DTD validation is requested
280    /// and the document is not valid against its DTD.
281    FODC0006,
282    /// The processor does not support serialization.
283    ///
284    /// Raised when fn:serialize is called and the processor does not support
285    /// serialization, in cases where the host language makes serialization an
286    /// optional feature.
287    FODC0010,
288    /// Invalid decimal format name.
289    ///
290    /// This error is raised if the decimal format name supplied to
291    /// fn:format-number is not a valid QName, or if the prefix in the QName is
292    /// undeclared, or if there is no decimal format in the static context with
293    /// a matching name.
294    FODF1280,
295    /// Invalid decimal format picture string.
296    ///
297    /// This error is raised if the picture string supplied to fn:format-number
298    /// or fn:format-integer has invalid syntax.
299    FODF1310,
300    /// Overflow/underflow in date/time operation.
301    ///
302    /// Raised when casting to date/time datatypes, or performing arithmetic
303    /// with date/time values, if arithmetic overflow or underflow occurs.
304    FODT0001,
305    /// err:FODT0002, Overflow/underflow in duration operation.
306    ///
307    /// Raised when casting to duration datatypes, or performing arithmetic
308    /// with duration values, if arithmetic overflow or underflow occurs.
309    FODT0002,
310    /// Invalid timezone value.
311    ///
312    /// Raised by adjust-date-to-timezone and related functions if the supplied
313    /// timezone is invalid.
314    FODT0003,
315    /// Unidentified error.
316    ///
317    /// Error code used by fn:error when no other error code is provided.
318    FOER0000,
319    /// Invalid date/time formatting parameters.
320    ///
321    /// This error is raised if the picture string or calendar supplied to
322    /// fn:format-date, fn:format-time, or fn:format-dateTime has invalid
323    /// syntax.
324    FOFD1340,
325    /// Invalid date/time formatting component.
326    ///
327    /// This error is raised if the picture string supplied to fn:format-date
328    /// selects a component that is not present in a date, or if the picture
329    /// string supplied to fn:format-time selects a component that is not
330    /// present in a time.
331    FOFD1350,
332    /// JSON syntax error.
333    ///
334    /// Raised by functions such as fn:json-doc, fn:parse-json or
335    /// fn:json-to-xml if the string supplied as input does not conform to the
336    /// JSON grammar (optionally with implementation-defined extensions).
337    FOJS0001,
338    /// JSON duplicate keys.
339    ///
340    /// Raised by functions such as map:merge, fn:json-doc, fn:parse-json or
341    /// fn:json-to-xml if the input contains duplicate keys, when the chosen
342    /// policy is to reject duplicates.
343    FOJS0003,
344    /// JSON: not schema-aware.
345    ///
346    /// Raised by fn:json-to-xml if validation is requested when the processor
347    /// does not support schema validation or typed nodes.
348    FOJS0004,
349    /// Invalid options.
350    ///
351    /// Raised by functions such as map:merge, fn:parse-json, and
352    /// fn:xml-to-json if the $options map contains an invalid entry.
353    FOJS0005,
354    /// Invalid XML representation of JSON.
355    ///
356    /// Raised by fn:xml-to-json if the XML input does not conform to the rules
357    /// for the XML representation of JSON.
358    FOJS0006,
359    /// Bad JSON escape sequence.
360    ///
361    /// Raised by fn:xml-to-json if the XML input uses the attribute
362    /// escaped="true" or escaped-key="true", and the corresponding string or
363    /// key contains an invalid JSON escape sequence.
364    FOJS0007,
365    /// No namespace found for prefix.
366    ///
367    /// Raised by fn:resolve-QName and analogous functions if a supplied QName
368    /// has a prefix that has no binding to a namespace.
369    FONS0004,
370    /// Base-uri not defined in the static context.
371    ///
372    /// Raised by fn:resolve-uri if no base URI is available for resolving a
373    /// relative URI.
374    FONS0005,
375    /// Module URI is a zero-length string.
376    ///
377    /// Raised by fn:load-xquery-module if the supplied module URI is zero-length.
378    FOQM0001,
379    /// Module URI not found.
380    ///
381    /// Raised by fn:load-xquery-module if no module can be found with the
382    /// supplied module URI.
383    FOQM0002,
384    /// Static error in dynamically-loaded XQuery module.
385    ///
386    /// Raised by fn:load-xquery-module if a static error (including a
387    /// statically-detected type error) is encountered when processing the
388    /// library module.
389    FOQM0003,
390    /// Parameter for dynamically-loaded XQuery module has incorrect type.
391    ///
392    /// Raised by fn:load-xquery-module if a value is supplied for the initial
393    /// context item or for an external variable, and the value does not
394    /// conform to the required type declared in the dynamically loaded module.
395    FOQM0005,
396    /// No suitable XQuery processor available.
397    ///
398    /// Raised by fn:load-xquery-module if no XQuery processor is available
399    /// supporting the requested XQuery version (or if none is available at
400    /// all).
401    FOQM0006,
402    /// Invalid value for cast/constructor.
403    ///
404    /// A general-purpose error raised when casting, if a cast between two
405    /// datatypes is allowed in principle, but the supplied value cannot be
406    /// converted: for example when attempting to cast the string "nine" to an
407    /// integer.
408    FORG0001,
409    /// Invalid argument to fn:resolve-uri().
410    ///
411    /// Raised when either argument to fn:resolve-uri is not a valid URI/IRI.
412    FORG0002,
413    /// fn:zero-or-one called with a sequence containing more than one item.
414    ///
415    /// Raised by fn:zero-or-one if the supplied value contains more than one item.
416    FORG0003,
417    /// fn:one-or-more called with a sequence containing no items.
418    ///
419    /// Raised by fn:one-or-more if the supplied value is an empty sequence.
420    FORG0004,
421    /// fn:exactly-one called with a sequence containing zero or more than one item.
422    ///
423    /// Raised by fn:exactly-one if the supplied value is not a singleton sequence.
424    FORG0005,
425    /// Invalid argument type.
426    ///
427    /// Raised by functions such as fn:max, fn:min, fn:avg, fn:sum if the
428    /// supplied sequence contains values inappropriate to this function.
429    FORG0006,
430    /// The two arguments to fn:dateTime have inconsistent timezones.
431    ///
432    /// Raised by fn:dateTime if the two arguments both have timezones and the
433    /// timezones are different.
434    FORG0008,
435    /// Error in resolving a relative URI against a base URI in fn:resolve-uri.
436    ///
437    /// A catch-all error for fn:resolve-uri, recognizing that the
438    /// implementation can choose between a variety of algorithms and that some
439    /// of these may fail for a variety of reasons.
440    FORG0009,
441    /// Invalid date/time.
442    ///
443    /// Raised when the input to fn:parse-ietf-date does not match the
444    /// prescribed grammar, or when it represents an invalid date/time such as
445    /// 31 February.
446    FORG0010,
447    /// Invalid regular expression flags.
448    ///
449    /// Raised by regular expression functions such as fn:matches and
450    /// fn:replace if the regular expression flags contain a character other
451    /// than i, m, q, s, or x.
452    FORX0001,
453    /// Invalid regular expression.
454    ///
455    /// Raised by regular expression functions such as fn:matches and
456    /// fn:replace if the regular expression is syntactically invalid.
457    FORX0002,
458    /// Regular expression matches zero-length string.
459    ///
460    /// For functions such as fn:replace and fn:tokenize, raises an error if
461    /// the supplied regular expression is capable of matching a zero length
462    /// string.
463    FORX0003,
464    /// Invalid replacement string.
465    ///
466    /// Raised by fn:replace to report errors in the replacement string.
467    FORX0004,
468    /// Argument to fn:data() contains a node that does not have a typed value.
469    ///
470    /// Raised by fn:data, or by implicit atomization, if applied to a node
471    /// with no typed value, the main example being an element validated
472    /// against a complex type that defines it to have element-only content.
473    FOTY0012,
474    /// The argument to fn:data() contains a function item.
475    ///
476    /// Raised by fn:data, or by implicit atomization, if the sequence to be
477    /// atomized contains a function item.
478    FOTY0013,
479    /// The argument to fn:string() is a function item.
480    ///
481    /// Raised by fn:string, or by implicit string conversion, if the input
482    /// sequence contains a function item.
483    FOTY0014,
484    /// An argument to fn:deep-equal() contains a function item.
485    ///
486    /// Raised by fn:deep-equal if either input sequence contains a function
487    /// item.
488    FOTY0015,
489    /// Invalid $href argument to fn:unparsed-text() (etc.)
490    ///
491    /// A dynamic error is raised if the $href argument contains a fragment
492    /// identifier, or if it cannot be used to retrieve a resource containing
493    /// text.
494    FOUT1170,
495    /// Cannot decode resource retrieved by fn:unparsed-text() (etc.)
496    ///
497    /// A dynamic error is raised if the retrieved resource contains octets
498    /// that cannot be decoded into Unicode ·characters· using the specified
499    /// encoding, or if the resulting characters are not permitted XML
500    /// characters. This includes the case where the processor does not support
501    /// the requested encoding.
502    FOUT1190,
503    /// Cannot infer encoding of resource retrieved by fn:unparsed-text()
504    /// (etc.)
505    ///
506    /// A dynamic error is raised if $encoding is absent and the processor
507    /// cannot infer the encoding using external information and the encoding
508    /// is not UTF-8.
509    FOUT1200,
510    /// No suitable XSLT processor available
511    ///
512    /// A dynamic error is raised if no XSLT processor suitable for evaluating
513    /// a call on fn:transform is available.
514    FOXT0001,
515    /// Invalid parameters to XSLT transformation
516    ///
517    /// A dynamic error is raised if the parameters supplied to fn:transform
518    /// are invalid, for example if two mutually-exclusive parameters are
519    /// supplied. If a suitable XSLT error code is available (for example in
520    /// the case where the requested initial-template does not exist in the
521    /// stylesheet), that error code should be used in preference.
522    FOXT0002,
523    /// XSLT transformation failed
524    ///
525    /// A dynamic error is raised if an XSLT transformation invoked using
526    /// fn:transform fails with a static or dynamic error. The XSLT error code
527    /// is used if available; this error code provides a fallback when no XSLT
528    /// error code is returned, for example because the processor is an XSLT
529    /// 1.0 processor.
530    FOXT0003,
531    /// XSLT transformation has been disabled
532    ///
533    /// A dynamic error is raised if the fn:transform function is invoked when
534    /// XSLT transformation (or a specific transformation option) has been
535    /// disabled for security or other reasons.
536    FOXT0004,
537    /// XSLT output contains non-accepted characters
538    ///
539    /// A dynamic error is raised if the result of the fn:transform function
540    /// contains characters available only in XML 1.1 and the calling processor
541    /// cannot handle such characters.
542    FOXT0006,
543
544    /// Duplicate global variable name.
545    ///
546    /// It is a static error if a package contains more than one non-hidden
547    /// binding of a global variable with the same name and same import
548    /// precedence, unless it also contains another binding with the same name
549    /// and higher import precedence.
550    XTSE0630,
551    /// Circularity
552    ///
553    /// Circularity in global declarations is now allowed.
554    XTDE0640,
555    /// Shallow copy
556    ///
557    /// Shallow copy of sequence of more than one item is not allowed.
558    XTTE3180,
559    /// Function item in complex content
560    ///
561    /// The result sequence to be added as content cannot contain a function
562    /// item.
563    XTDE0450,
564
565    /// Function cannot be normalized for serialization.
566    ///
567    /// It is an error if an item in S in sequence normalization is an
568    /// attribute node or a namespace node.
569    SENR0001,
570
571    /// Entity serialization error
572    ///
573    /// The serializer is unable to satisfy the rules for either a well-formed
574    /// XML document entity or a well-formed XML external general parsed
575    /// entity, or both, except for content modified by the character expansion
576    /// phase of serialization.
577    SERE0003,
578
579    /// Standalone or doctype-system parameter disallowed for XML fragment.
580    ///
581    /// It's not allowed to specify the doctype-system parameter, or to specify
582    /// the standalone parameter with a value other than omit, if the instance
583    /// of the data model contains text nodes or multiple element nodes as
584    /// children of the root node.
585    SEPM0004,
586
587    /// Invalid character in NCName according to namespaces version.
588    ///
589    /// It is an error if the serialized result would contain an NCNameNames
590    /// that contains a character that is not permitted by the version of
591    /// Namespaces in XML specified by the version parameter.
592    SERE0005,
593
594    /// Invalid character according to XML version
595    ///
596    /// It is an error if the serialized result would contain a character that
597    /// is not permitted by the version of XML specified by the version
598    /// parameter.
599    SERE0006,
600
601    /// Invalid encoding
602    ///
603    /// It is an error if an output encoding other than UTF-8 or UTF-16 is
604    /// requested and the serializer does not support that encoding.
605    SESU0007,
606
607    /// Illegal character for encoding
608    ///
609    /// It is an error if a character that cannot be represented in the
610    /// encoding that the serializer is using for output appears in a context
611    /// where character references are not allowed (for example if the
612    /// character occurs in the name of an element).
613    SERE0008,
614
615    /// standalone even though XML declaration is omitted
616    ///
617    /// It is an error if the omit-xml-declaration parameter has the value yes,
618    /// true or 1, and the standalone attribute has a value other than omit; or
619    /// the version parameter has a value other than 1.0 and the doctype-system
620    /// parameter is specified.
621    SEPM0009,
622
623    /// undeclare-prefixes is not allowed in XML version 1.0
624    ///
625    /// It is an error if the output method is xml or xhtml, the value of the
626    /// undeclare-prefixes parameter is one of, yes, true or 1, and the value
627    /// of the version parameter is 1.0.
628    SEPM0010,
629
630    /// Unsupported normalization form
631    ///
632    /// It is an error if the value of the normalization-form parameter
633    /// specifies a normalization form that is not supported by the serializer.
634    SESU0011,
635
636    /// Combining character at start of fully-normalized result
637    ///
638    /// It is an error if the value of the normalization-form parameter is
639    /// fully-normalized and any relevant construct of the result begins with a
640    /// combining character.
641    SERE0012,
642
643    /// Unsupported version
644    ///
645    /// It is an error if the serializer does not support the version of XML or
646    /// HTML specified by the version parameter.
647    SESU0013,
648
649    /// Illegal characters in HTML output.
650    ///
651    /// It is an error to use the HTML output method if characters which are
652    /// permitted in XML but not in HTML appear in the instance of the data
653    /// model.
654    SERE0014,
655
656    /// Illegal characters in processing instruction for HTML output.
657    ///
658    /// It is an error to use the HTML output method when > appears within a
659    /// processing instruction in the data model instance being serialized.
660    SERE0015,
661
662    /// Parameter value is invalid for the defined domain.
663    SEPM0016,
664
665    /// Error evaluating serialization parameter expression.
666    ///
667    /// It is an error if evaluating an expression in order to extract the
668    /// setting of a serialization parameter from a data model instance would
669    /// yield an error.
670    SEPM0017,
671
672    /// Multiple values for use-character-maps serialization parameter.
673    ///
674    /// It is an error if evaluating an expression in order to extract the
675    /// setting of the use-character-maps serialization parameter from a data
676    /// model instance would yield a sequence of length greater than one.
677    SEPM0018,
678
679    /// Multiple values for serialization parameter.
680    ///
681    /// It is an error if an instance of the data model used to specify the
682    /// settings of serialization parameters specifies the value of the same
683    /// parameter more than once.
684    SEPM0019,
685
686    /// Invalid numeric value in JSON.
687    ///
688    /// It is an error if a numeric value being serialized using the JSON
689    /// output method cannot be represented in the JSON grammar (e.g. +INF,
690    /// -INF, NaN).
691    SERE0020,
692
693    /// Item not allowed in JSON output.
694    ///
695    /// It is an error if a sequence being serialized using the JSON output
696    /// method includes items for which no rules are provided in the
697    /// appropriate section of the serialization rules.
698    SERE0021,
699
700    /// Duplicate key in JSON output.
701    ///
702    /// It is an error if a map being serialized using the JSON output method
703    /// has two keys with the same string value, unless the
704    /// allow-duplicate-names has the value yes, true or 1.
705    SERE0022,
706
707    /// Sequence of length greater than one in JSON output.
708    ///
709    /// It is an error if a sequence being serialized using the JSON output
710    /// method is of length greater than one.
711    SERE0023,
712
713    /// An application generated error
714    Application(Box<ApplicationError>),
715}
716
717#[derive(Debug, Clone, PartialEq)]
718#[cfg_attr(feature = "serde", derive(serde::Serialize))]
719pub struct ApplicationError {
720    qname: xot::xmlname::OwnedName,
721    description: String,
722    // FIXME: error object is not supported right now
723    // it would require storing an arbitrary sequence in here,
724    // but that's not really supported by this simple error.
725}
726
727impl ApplicationError {
728    pub fn new(qname: xot::xmlname::OwnedName, description: String) -> Self {
729        Self { qname, description }
730    }
731}
732
733impl Error {
734    pub fn with_span(self, span: SourceSpan) -> SpannedError {
735        SpannedError {
736            error: self,
737            span: Some(span),
738        }
739    }
740    pub fn with_ast_span(self, span: xee_xpath_ast::ast::Span) -> SpannedError {
741        Self::with_span(self, span.into())
742    }
743
744    pub fn code(&self) -> String {
745        match self {
746            Error::Application(application_error) => {
747                application_error.qname.local_name().to_string()
748            }
749            _ => self.to_string(),
750        }
751    }
752
753    pub fn code_qname(&self) -> xot::xmlname::OwnedName {
754        match self {
755            Error::Application(application_error) => application_error.qname.clone(),
756            _ => xot::xmlname::OwnedName::new(
757                self.code(),
758                "http://www.w3.org/2005/xqt-errors".to_string(),
759                "".to_string(),
760            ),
761        }
762    }
763
764    pub fn message(&self) -> &str {
765        self.documentation_pieces().0
766    }
767
768    pub fn note(&self) -> &str {
769        self.documentation_pieces().1
770    }
771
772    fn documentation_pieces(&self) -> (&str, &str) {
773        if let Some(documentation) = self.get_documentation() {
774            let mut pieces = documentation.splitn(2, "\n\n");
775            let first = pieces.next().unwrap_or("");
776            let second = pieces.next().unwrap_or("");
777            (first, second)
778        } else {
779            ("", "")
780        }
781    }
782}
783impl std::error::Error for Error {}
784
785impl std::fmt::Display for SpannedError {
786    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
787        if let Some(span) = self.span {
788            let span = span.range();
789            write!(f, "{} ({}..{})", self.error, span.start, span.end)
790        } else {
791            write!(f, "{}", self.error)
792        }
793    }
794}
795
796impl std::error::Error for SpannedError {}
797
798// note: this is only used for internal conversions of names
799// for now, not the full grammar.
800impl From<xee_xpath_ast::ParserError> for Error {
801    fn from(e: xee_xpath_ast::ParserError) -> Self {
802        let spanned_error: SpannedError = e.into();
803        spanned_error.error
804    }
805}
806
807impl From<xee_xpath_ast::ParserError> for SpannedError {
808    fn from(e: xee_xpath_ast::ParserError) -> Self {
809        let span = e.span();
810        let error = match e {
811            ParserError::ExpectedFound { .. } => Error::XPST0003,
812            // this is what fn-function-arity-017 expects, even though
813            // implementation limit exceeded (XPST00130) seems reasonable to me.
814            ParserError::ArityOverflow { .. } => Error::FOAR0002,
815            ParserError::Reserved { .. } => Error::XPST0003,
816            ParserError::UnknownPrefix { .. } => Error::XPST0081,
817            ParserError::UnknownType { .. } => Error::XPST0051,
818            // TODO: this this the right error code?
819            ParserError::IllegalFunctionInPattern { .. } => Error::XPST0003,
820        };
821        SpannedError {
822            error,
823            span: Some(span.into()),
824        }
825    }
826}
827
828impl From<regexml::Error> for Error {
829    fn from(e: regexml::Error) -> Self {
830        use regexml::Error::*;
831        // TODO: pass more error details into error codes
832        match e {
833            Internal => panic!("Internal error in regexml engine"),
834            InvalidFlags(_) => Error::FORX0001,
835            Syntax(_) => Error::FORX0002,
836            MatchesEmptyString => Error::FORX0003,
837            InvalidReplacementString(_) => Error::FORX0004,
838        }
839    }
840}
841
842impl From<xot::Error> for Error {
843    fn from(e: xot::Error) -> Self {
844        match e {
845            xot::Error::MissingPrefix(_) => Error::XPST0081,
846            // TODO: are there other xot errors that need to be translated?
847            _ => Error::XPST0003,
848        }
849    }
850}
851
852impl From<Error> for SpannedError {
853    fn from(e: Error) -> Self {
854        SpannedError {
855            error: e,
856            span: None,
857        }
858    }
859}
860
861// impl From<xee_name::Error> for Error {
862//     fn from(e: xee_name::Error) -> Self {
863//         match e {
864//             xee_name::Error::MissingPrefix => Error::XPST0081,
865//         }
866//     }
867// }
868
869impl From<OutOfBoundsError> for Error {
870    fn from(_e: OutOfBoundsError) -> Self {
871        Error::FOCA0003
872    }
873}
874
875/// The result type for errors without span information.
876pub type Result<T> = std::result::Result<T, Error>;
877
878/// The result type for errors with (optional) source spans.
879///
880/// Also known as `SpannedResult` internally.
881pub type SpannedResult<T> = std::result::Result<T, SpannedError>;
882
883impl SpannedError {
884    /// get the underlying [`Error`] value
885    pub fn value(self) -> Error {
886        self.error
887    }
888}