Skip to main content

fsm_guards/
error.rs

1use std::fmt;
2
3/// Error returned by the low-level `engine::apply` tier.
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum ApplyError {
6    UnknownOperator(String),
7    InvalidArguments(String),
8    /// A registered custom operator returned `Err`. Carries the operator name
9    /// and the error message so `evaluate()` can surface them in `GuardError::CustomOpFailed`.
10    CustomOpFailed { op: String, source: String },
11    /// In-loop fuel budget exhausted. Internal variant; `evaluate()` maps this
12    /// to `GuardError::FuelExceeded { limit }`.
13    #[doc(hidden)]
14    FuelExceeded,
15}
16
17impl fmt::Display for ApplyError {
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        match self {
20            Self::UnknownOperator(op) => write!(f, "unknown operator: {op}"),
21            Self::InvalidArguments(msg) => write!(f, "invalid arguments: {msg}"),
22            Self::CustomOpFailed { op, source } => {
23                write!(f, "custom operator '{op}' failed: {source}")
24            }
25            Self::FuelExceeded => write!(f, "fuel budget exhausted"),
26        }
27    }
28}
29
30impl std::error::Error for ApplyError {}
31
32/// Error returned by the high-level `evaluate()` tier.
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub enum GuardError {
35    /// Structural AST problem or unsupported operator.
36    Malformed(String),
37    /// `{"var": "X"}` where `X`'s root key is absent from the data object.
38    /// Detected via pre-walk; names the offending path explicitly.
39    MissingVar(String),
40    /// Type coercion or argument-arity error from the evaluator.
41    TypeError(String),
42    /// In-loop node budget exhausted before evaluation completed.
43    FuelExceeded { limit: usize },
44    /// A registered custom operator returned `Err(...)`.
45    CustomOpFailed { op: String, source: String },
46}
47
48impl fmt::Display for GuardError {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        match self {
51            Self::Malformed(msg) => write!(f, "guard rule malformed: {msg}"),
52            Self::MissingVar(path) => write!(f, "guard references missing variable '{path}'"),
53            Self::TypeError(msg) => write!(f, "guard type error: {msg}"),
54            Self::FuelExceeded { limit } => {
55                write!(f, "guard rule too complex (node limit: {limit})")
56            }
57            Self::CustomOpFailed { op, source } => {
58                write!(f, "custom operator '{op}' failed: {source}")
59            }
60        }
61    }
62}
63
64impl std::error::Error for GuardError {}