use thiserror::Error;
#[derive(Debug, Error, Clone)]
pub enum PlanError {
#[error("invalid {kind} '{value}': {reason}")]
InvalidIdentifier {
kind: String,
value: String,
reason: String,
},
#[error("duplicate rule key '{0}'")]
DuplicateRuleKey(String),
#[error("missing dependency: '{from}' recalls '{to}'")]
MissingDependency { from: String, to: String },
#[error("cycle detected in rule graph: {0:?}")]
CycleDetected(Vec<String>),
#[error("pool not found for section '{section}', field '{field}'")]
PoolRefNotFound { section: String, field: String },
#[error("invalid probability for rule '{rule}': {value}")]
InvalidChanceProbability { rule: String, value: f64 },
#[error("weighted expression for rule '{rule}' has a total weight of 0")]
WeightedTotalZero { rule: String },
}
#[derive(Debug, Clone)]
pub struct PlanErrorReport {
pub errors: Vec<PlanError>,
}
impl std::fmt::Display for PlanErrorReport {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.errors.is_empty() {
return write!(f, "plan validation failed with no reported errors");
}
for (idx, error) in self.errors.iter().enumerate() {
if idx > 0 {
write!(f, "; ")?;
}
write!(f, "{error}")?;
}
Ok(())
}
}
impl std::error::Error for PlanErrorReport {}
#[derive(Debug, Error)]
pub enum AethelError {
#[error("pool not found for section '{section}', field '{field}'")]
PoolNotFound { section: String, field: String },
#[error("missing dependency in generation context: '{0}'")]
MissingDependency(String),
#[error("{0}")]
Custom(String),
}