zen_engine/
error.rs

1use crate::engine::EvaluationTraceKind;
2use crate::loader::LoaderError;
3use crate::DecisionGraphValidationError;
4use serde::ser::SerializeMap;
5use serde::{Serialize, Serializer};
6use serde_json::Value;
7use std::sync::Arc;
8use thiserror::Error;
9use zen_types::variable::Variable;
10
11#[derive(Debug, Error)]
12pub enum EvaluationError {
13    #[error("Loader error")]
14    LoaderError(LoaderError),
15
16    #[error("{source}")]
17    NodeError {
18        node_id: Arc<str>,
19        trace: Option<Variable>,
20        source: Box<dyn std::error::Error>,
21    },
22
23    #[error("Depth limit exceeded")]
24    DepthLimitExceeded,
25
26    #[error("Invalid graph")]
27    InvalidGraph(DecisionGraphValidationError),
28
29    #[error("Validation failed")]
30    Validation(Value),
31}
32
33impl EvaluationError {
34    pub fn serialize_with_mode<S>(
35        &self,
36        serializer: S,
37        mode: EvaluationTraceKind,
38    ) -> Result<S::Ok, S::Error>
39    where
40        S: Serializer,
41    {
42        let mut map = serializer.serialize_map(None)?;
43
44        match self {
45            EvaluationError::DepthLimitExceeded => {
46                map.serialize_entry("type", "DepthLimitExceeded")?;
47            }
48            EvaluationError::NodeError {
49                node_id,
50                trace,
51                source,
52            } => {
53                map.serialize_entry("type", "NodeError")?;
54                map.serialize_entry("source", &source.to_string())?;
55                map.serialize_entry("nodeId", &node_id)?;
56
57                if let Some(trace) = &trace {
58                    map.serialize_entry("trace", &mode.serialize_trace(trace))?;
59                }
60            }
61            EvaluationError::LoaderError(err) => {
62                map.serialize_entry("type", "LoaderError")?;
63                match err {
64                    LoaderError::Internal { key, source } => {
65                        map.serialize_entry("key", key)?;
66                        map.serialize_entry("source", &source.to_string())?;
67                    }
68                    LoaderError::NotFound(key) => {
69                        map.serialize_entry("key", key)?;
70                    }
71                }
72            }
73            EvaluationError::InvalidGraph(err) => {
74                map.serialize_entry("type", "InvalidGraph")?;
75                map.serialize_entry("source", err)?;
76            }
77            EvaluationError::Validation(err) => {
78                map.serialize_entry("type", "Validation")?;
79                map.serialize_entry("source", err)?;
80            }
81        }
82
83        map.end()
84    }
85}
86
87impl Serialize for EvaluationError {
88    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
89    where
90        S: Serializer,
91    {
92        self.serialize_with_mode(serializer, Default::default())
93    }
94}
95
96impl From<LoaderError> for Box<EvaluationError> {
97    fn from(error: LoaderError) -> Self {
98        Box::new(EvaluationError::LoaderError(error.into()))
99    }
100}
101
102impl From<DecisionGraphValidationError> for Box<EvaluationError> {
103    fn from(error: DecisionGraphValidationError) -> Self {
104        Box::new(EvaluationError::InvalidGraph(error.into()))
105    }
106}