Skip to main content

cel_core/eval/
error.rs

1//! Evaluation error types.
2
3use std::fmt;
4
5/// An error that occurred during CEL evaluation.
6#[derive(Debug, Clone)]
7pub struct EvalError {
8    /// The error message.
9    pub message: String,
10    /// The kind of error.
11    pub kind: EvalErrorKind,
12}
13
14/// The kind of evaluation error.
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum EvalErrorKind {
17    /// Division by zero.
18    DivisionByZero,
19    /// Modulo by zero.
20    ModuloByZero,
21    /// Integer overflow.
22    Overflow,
23    /// Value out of valid range.
24    RangeError,
25    /// Type mismatch at runtime.
26    TypeMismatch,
27    /// Unknown identifier (variable not found).
28    UnknownIdentifier,
29    /// Unknown function.
30    UnknownFunction,
31    /// Index out of bounds.
32    IndexOutOfBounds,
33    /// Key not found in map.
34    KeyNotFound,
35    /// Invalid argument.
36    InvalidArgument,
37    /// No matching overload found.
38    NoMatchingOverload,
39    /// Field not found on struct/message.
40    FieldNotFound,
41    /// Invalid conversion.
42    InvalidConversion,
43    /// Internal error (unexpected state).
44    Internal,
45}
46
47impl EvalError {
48    /// Create a new error with the given kind and message.
49    pub fn new(kind: EvalErrorKind, message: impl Into<String>) -> Self {
50        Self {
51            message: message.into(),
52            kind,
53        }
54    }
55
56    /// Create a division by zero error.
57    pub fn division_by_zero() -> Self {
58        Self::new(EvalErrorKind::DivisionByZero, "division by zero")
59    }
60
61    /// Create a modulo by zero error.
62    pub fn modulo_by_zero() -> Self {
63        Self::new(EvalErrorKind::ModuloByZero, "modulo by zero")
64    }
65
66    /// Create an overflow error.
67    pub fn overflow(message: impl Into<String>) -> Self {
68        Self::new(EvalErrorKind::Overflow, message)
69    }
70
71    /// Create a range error (value out of valid range).
72    pub fn range_error(message: impl Into<String>) -> Self {
73        Self::new(EvalErrorKind::RangeError, message)
74    }
75
76    /// Create a type mismatch error.
77    pub fn type_mismatch(expected: &str, actual: &str) -> Self {
78        Self::new(
79            EvalErrorKind::TypeMismatch,
80            format!("expected {}, got {}", expected, actual),
81        )
82    }
83
84    /// Create an unknown identifier error.
85    pub fn unknown_identifier(name: &str) -> Self {
86        Self::new(
87            EvalErrorKind::UnknownIdentifier,
88            format!("unknown identifier: {}", name),
89        )
90    }
91
92    /// Create an unknown function error.
93    pub fn unknown_function(name: &str) -> Self {
94        Self::new(
95            EvalErrorKind::UnknownFunction,
96            format!("unknown function: {}", name),
97        )
98    }
99
100    /// Create an index out of bounds error.
101    pub fn index_out_of_bounds(index: i64, len: usize) -> Self {
102        Self::new(
103            EvalErrorKind::IndexOutOfBounds,
104            format!("index {} out of bounds for length {}", index, len),
105        )
106    }
107
108    /// Create a key not found error.
109    pub fn key_not_found(key: &str) -> Self {
110        Self::new(
111            EvalErrorKind::KeyNotFound,
112            format!("key not found: {}", key),
113        )
114    }
115
116    /// Create an invalid argument error.
117    pub fn invalid_argument(message: impl Into<String>) -> Self {
118        Self::new(EvalErrorKind::InvalidArgument, message)
119    }
120
121    /// Create a no matching overload error.
122    pub fn no_matching_overload(func: &str) -> Self {
123        Self::new(
124            EvalErrorKind::NoMatchingOverload,
125            format!("no matching overload for function: {}", func),
126        )
127    }
128
129    /// Create a field not found error.
130    pub fn field_not_found(field: &str) -> Self {
131        Self::new(
132            EvalErrorKind::FieldNotFound,
133            format!("field not found: {}", field),
134        )
135    }
136
137    /// Create an invalid conversion error.
138    pub fn invalid_conversion(from: &str, to: &str) -> Self {
139        Self::new(
140            EvalErrorKind::InvalidConversion,
141            format!("cannot convert {} to {}", from, to),
142        )
143    }
144
145    /// Create an internal error.
146    pub fn internal(message: impl Into<String>) -> Self {
147        Self::new(EvalErrorKind::Internal, message)
148    }
149}
150
151impl fmt::Display for EvalError {
152    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153        write!(f, "{}", self.message)
154    }
155}
156
157impl std::error::Error for EvalError {}
158
159impl From<&str> for EvalError {
160    fn from(s: &str) -> Self {
161        Self::new(EvalErrorKind::Internal, s)
162    }
163}
164
165impl From<String> for EvalError {
166    fn from(s: String) -> Self {
167        Self::new(EvalErrorKind::Internal, s)
168    }
169}