Skip to main content

anathema_templates/error/
mod.rs

1use std::error::Error as StdError;
2use std::fmt::{self, Display, Formatter};
3use std::path::PathBuf;
4
5pub(crate) use self::parse::{ParseError, ParseErrorKind, src_line_no};
6
7mod parse;
8
9pub type Result<T, E = Error> = std::result::Result<T, E>;
10
11#[derive(Debug)]
12pub struct Error {
13    pub template_path: Option<PathBuf>,
14    pub kind: ErrorKind,
15}
16
17impl Error {
18    pub fn new(path: Option<PathBuf>, kind: impl Into<ErrorKind>) -> Self {
19        Self {
20            kind: kind.into(),
21            template_path: path,
22        }
23    }
24
25    pub fn no_template(kind: ErrorKind) -> Self {
26        Self {
27            kind,
28            template_path: None,
29        }
30    }
31
32    pub fn path(&self) -> String {
33        match self.template_path.as_ref() {
34            Some(path) => format!("{}", path.display()),
35            None => String::new(),
36        }
37    }
38}
39
40impl Display for Error {
41    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
42        self.kind.fmt(f)
43    }
44}
45
46impl StdError for Error {}
47
48#[derive(Debug)]
49pub enum ErrorKind {
50    ParseError(ParseError),
51    CircularDependency,
52    MissingComponent(String),
53    EmptyTemplate,
54    EmptyBody,
55    InvalidStatement(String),
56    Io(std::io::Error),
57    GlobalAlreadyAssigned(String),
58}
59
60impl ErrorKind {
61    pub(crate) fn to_error(self, template: Option<PathBuf>) -> Error {
62        Error::new(template, self)
63    }
64}
65
66impl Display for ErrorKind {
67    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
68        match self {
69            ErrorKind::ParseError(err) => write!(f, "{err}"),
70            ErrorKind::CircularDependency => write!(f, "circular dependency"),
71            ErrorKind::MissingComponent(name) => write!(f, "`@{name}` is not a registered component"),
72            ErrorKind::EmptyTemplate => write!(f, "empty template"),
73            ErrorKind::EmptyBody => write!(f, "if or else node has no children"),
74            ErrorKind::InvalidStatement(stmt) => write!(f, "invalid statement: {stmt}"),
75            ErrorKind::Io(err) => write!(f, "{err}"),
76            ErrorKind::GlobalAlreadyAssigned(name) => write!(f, "global value `{name}` already assigned"),
77        }
78    }
79}
80
81impl From<ParseError> for ErrorKind {
82    fn from(value: ParseError) -> Self {
83        Self::ParseError(value)
84    }
85}
86
87impl From<std::io::Error> for ErrorKind {
88    fn from(value: std::io::Error) -> Self {
89        Self::Io(value)
90    }
91}