anathema-templates 0.2.11

Anathema template parser (aml)
Documentation
use std::error::Error as StdError;
use std::fmt::{self, Display, Formatter};
use std::path::PathBuf;

pub(crate) use self::parse::{ParseError, ParseErrorKind, src_line_no};

mod parse;

pub type Result<T, E = Error> = std::result::Result<T, E>;

#[derive(Debug)]
pub struct Error {
    pub template_path: Option<PathBuf>,
    pub kind: ErrorKind,
}

impl Error {
    pub fn new(path: Option<PathBuf>, kind: impl Into<ErrorKind>) -> Self {
        Self {
            kind: kind.into(),
            template_path: path,
        }
    }

    pub fn no_template(kind: ErrorKind) -> Self {
        Self {
            kind,
            template_path: None,
        }
    }

    pub fn path(&self) -> String {
        match self.template_path.as_ref() {
            Some(path) => format!("{}", path.display()),
            None => String::new(),
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        self.kind.fmt(f)
    }
}

impl StdError for Error {}

#[derive(Debug)]
pub enum ErrorKind {
    ParseError(ParseError),
    CircularDependency,
    MissingComponent(String),
    EmptyTemplate,
    EmptyBody,
    InvalidStatement(String),
    Io(std::io::Error),
    GlobalAlreadyAssigned(String),
}

impl ErrorKind {
    pub(crate) fn to_error(self, template: Option<PathBuf>) -> Error {
        Error::new(template, self)
    }
}

impl Display for ErrorKind {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            ErrorKind::ParseError(err) => write!(f, "{err}"),
            ErrorKind::CircularDependency => write!(f, "circular dependency"),
            ErrorKind::MissingComponent(name) => write!(f, "`@{name}` is not a registered component"),
            ErrorKind::EmptyTemplate => write!(f, "empty template"),
            ErrorKind::EmptyBody => write!(f, "if or else node has no children"),
            ErrorKind::InvalidStatement(stmt) => write!(f, "invalid statement: {stmt}"),
            ErrorKind::Io(err) => write!(f, "{err}"),
            ErrorKind::GlobalAlreadyAssigned(name) => write!(f, "global value `{name}` already assigned"),
        }
    }
}

impl From<ParseError> for ErrorKind {
    fn from(value: ParseError) -> Self {
        Self::ParseError(value)
    }
}

impl From<std::io::Error> for ErrorKind {
    fn from(value: std::io::Error) -> Self {
        Self::Io(value)
    }
}