use serde::Serialize;
use std::fmt;
#[derive(Debug, Serialize)]
#[serde(tag = "type", content = "data")]
pub enum AtentoError {
Io {
path: String,
#[serde(serialize_with = "serialize_io_error")]
source: std::io::Error,
},
YamlParse {
context: String,
#[serde(serialize_with = "serialize_yaml_error")]
source: serde_yaml::Error,
},
JsonSerialize { message: String },
Validation(String),
Execution(String),
StepExecution { step: String, reason: String },
TypeConversion { expected: String, got: String },
UnresolvedReference { reference: String, context: String },
Timeout { context: String, timeout_secs: u64 },
Runner(String),
}
fn serialize_io_error<S>(
error: &std::io::Error,
serializer: S,
) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&error.to_string())
}
fn serialize_yaml_error<S>(
error: &serde_yaml::Error,
serializer: S,
) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&error.to_string())
}
impl fmt::Display for AtentoError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Io { path, source } => {
write!(f, "Failed to read file '{path}': {source}")
}
Self::YamlParse { context, source } => {
write!(f, "Failed to parse YAML in '{context}': {source}")
}
Self::JsonSerialize { message } => {
write!(f, "Failed to serialize results: {message}")
}
Self::Validation(msg) => {
write!(f, "Chain validation failed: {msg}")
}
Self::Execution(msg) => {
write!(f, "Chain execution failed: {msg}")
}
Self::StepExecution { step, reason } => {
write!(f, "Step '{step}' failed: {reason}")
}
Self::TypeConversion { expected, got } => {
write!(f, "Expected {expected} value, got: {got}")
}
Self::UnresolvedReference { reference, context } => {
write!(f, "Unresolved reference '{reference}' in {context}")
}
Self::Timeout {
context,
timeout_secs,
} => {
write!(f, "{context} timeout after {timeout_secs}s")
}
Self::Runner(msg) => {
write!(f, "Runner error: {msg}")
}
}
}
}
impl std::error::Error for AtentoError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Io { source, .. } => Some(source),
Self::YamlParse { source, .. } => Some(source),
_ => None,
}
}
}
impl From<serde_json::Error> for AtentoError {
fn from(err: serde_json::Error) -> Self {
Self::JsonSerialize {
message: err.to_string(),
}
}
}
pub type Result<T> = std::result::Result<T, AtentoError>;