use std::fmt::{self, Display, Formatter};
use pest::RuleType;
pub type HenResult<T> = Result<T, HenError>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HenErrorKind {
Cli,
Input,
Io,
Parse,
Planner,
Execution,
Benchmark,
Prompt,
}
impl HenErrorKind {
pub fn label(self) -> &'static str {
match self {
HenErrorKind::Cli => "CLI",
HenErrorKind::Input => "Input",
HenErrorKind::Io => "IO",
HenErrorKind::Parse => "Parse",
HenErrorKind::Planner => "Planner",
HenErrorKind::Execution => "Execution",
HenErrorKind::Benchmark => "Benchmark",
HenErrorKind::Prompt => "Prompt",
}
}
}
#[derive(Debug, Clone)]
pub struct HenError {
kind: HenErrorKind,
summary: String,
details: Vec<String>,
exit_code: i32,
}
impl HenError {
pub fn new(kind: HenErrorKind, summary: impl Into<String>) -> Self {
Self {
kind,
summary: summary.into(),
details: Vec::new(),
exit_code: 1,
}
}
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.details.push(detail.into());
self
}
pub fn with_exit_code(mut self, code: i32) -> Self {
self.exit_code = code;
self
}
pub fn kind(&self) -> HenErrorKind {
self.kind
}
pub fn exit_code(&self) -> i32 {
self.exit_code
}
}
impl Display for HenError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln!(f, "[{}] {}", self.kind.label(), self.summary)?;
for detail in &self.details {
writeln!(f, " - {}", detail)?;
}
Ok(())
}
}
impl std::error::Error for HenError {}
pub fn print_error(err: &HenError) {
eprint!("{}", err);
}
impl<T> From<pest::error::Error<T>> for HenError
where
T: RuleType + fmt::Debug,
{
fn from(err: pest::error::Error<T>) -> Self {
HenError::new(HenErrorKind::Parse, "Failed to parse hen file").with_detail(err.to_string())
}
}