Skip to main content

ferrobridge_fhirpath/eval/
error.rs

1// SPDX-FileCopyrightText: Cadasto B.V.
2// SPDX-License-Identifier: BUSL-1.1
3
4//! The evaluation errors: every case where N1 says "the evaluation will end
5//! and signal an error to the calling environment", and the seams' failures.
6//! An error is never an empty result.
7
8use crate::seam::SeamError;
9use crate::temporal::arithmetic::ArithmeticError;
10
11/// Why an evaluation ended without a result.
12#[derive(Debug, thiserror::Error)]
13pub enum EvalError {
14    /// An operation that takes one item met several (N1 §4.5).
15    #[error("{operation} expects a single item, the collection holds {count}")]
16    Singleton {
17        /// The operator or function.
18        operation: String,
19        /// The number of items found.
20        count: usize,
21    },
22    /// An operation met an item of a type it does not take.
23    #[error("{operation} does not apply to {found}")]
24    Type {
25        /// The operator or function.
26        operation: String,
27        /// What it met.
28        found: String,
29    },
30    /// A function N1 and FHIR R4 do not define.
31    #[error("the function {name}() is not defined")]
32    UnknownFunction {
33        /// The function name.
34        name: String,
35    },
36    /// A function called with the wrong number of arguments.
37    #[error("{function}() takes {expected} argument(s), {found} given")]
38    Arity {
39        /// The function name.
40        function: String,
41        /// The admitted counts.
42        expected: &'static str,
43        /// The count given.
44        found: usize,
45    },
46    /// A member no type of the input defines (N1 §3).
47    #[error("{type_name} has no element {element}")]
48    UnknownElement {
49        /// The type, or the types, navigated from.
50        type_name: String,
51        /// The member name.
52        element: String,
53    },
54    /// The expression starts with a type name that is not the context's
55    /// type (N1 §3).
56    #[error("the expression names the type {named}, the context is a {context}")]
57    ContextType {
58        /// The type the expression names.
59        named: String,
60        /// The type of the context.
61        context: String,
62    },
63    /// A type specifier that names no type (N1 §6.3.1).
64    #[error("{name} names no type of the model")]
65    UnknownType {
66        /// The specifier as written.
67        name: String,
68    },
69    /// An environment variable the environment does not define (N1 §9).
70    #[error("the environment variable %{name} is not defined")]
71    UnknownVariable {
72        /// The variable name.
73        name: String,
74    },
75    /// A function whose seam the environment does not supply.
76    #[error("{function}() needs a seam the environment does not supply")]
77    NoSeam {
78        /// The function name.
79        function: &'static str,
80    },
81    /// A seam failed.
82    #[error("the seam behind {function}() failed")]
83    Seam {
84        /// The function name.
85        function: &'static str,
86        /// The seam's failure.
87        #[source]
88        source: SeamError,
89    },
90    /// A regular expression that does not compile.
91    #[error("the regular expression {pattern:?} does not compile")]
92    Regex {
93        /// The pattern.
94        pattern: String,
95        /// The compiler's failure.
96        #[source]
97        source: regex::Error,
98    },
99    /// Date and time arithmetic outside its rules (N1 §6.7).
100    #[error("date and time arithmetic failed")]
101    Arithmetic {
102        /// The failure.
103        #[source]
104        source: ArithmeticError,
105    },
106    /// The document contradicts the model, as a string where an object
107    /// belongs.
108    #[error("the element {element} contradicts the model: {reason}")]
109    Document {
110        /// The element path.
111        element: String,
112        /// What is wrong.
113        reason: String,
114    },
115    /// An element carries a modifier extension `checkModifiers()` does not
116    /// admit (FHIR R4 §2.9.1.5).
117    #[error("the element carries the modifier extension {url}, which the call does not admit")]
118    Modifier {
119        /// The extension's url.
120        url: String,
121    },
122    /// An order-dependent operation over a collection whose order N1 §3.1
123    /// leaves undefined, refused in the strict ordering mode.
124    #[error(
125        "{operation} needs an ordered input, and the order of a collection derived from children() or descendants() is undefined"
126    )]
127    Unordered {
128        /// The function name, or `[]` for the indexer.
129        operation: String,
130    },
131    /// An argument outside what the function admits.
132    #[error("{function}() received an invalid argument: {reason}")]
133    Argument {
134        /// The function name.
135        function: String,
136        /// What is wrong.
137        reason: String,
138    },
139}
140
141impl EvalError {
142    /// A type error for `operation` meeting `found`.
143    pub(crate) fn type_error(operation: impl Into<String>, found: impl Into<String>) -> Self {
144        Self::Type {
145            operation: operation.into(),
146            found: found.into(),
147        }
148    }
149
150    /// A singleton error for `operation` meeting `count` items.
151    pub(crate) fn singleton(operation: impl Into<String>, count: usize) -> Self {
152        Self::Singleton {
153            operation: operation.into(),
154            count,
155        }
156    }
157}