use std::error::Error as StdError;
use std::fmt;
pub type Result<T> = std::result::Result<T, Error>;
pub struct Error {
inner: Box<Inner>,
}
pub(crate) type Source = Box<dyn StdError + Send + Sync>;
struct Inner {
kind: Kind,
source: Option<Source>,
}
impl Error {
pub(crate) fn new(kind: Kind) -> Error {
Error {
inner: Box::new(Inner { kind, source: None }),
}
}
pub(crate) fn with<S: Into<Source>>(mut self, source: S) -> Error {
self.inner.source = Some(source.into());
self
}
pub fn kind(&self) -> &Kind {
&self.inner.kind
}
}
impl fmt::Debug for Error {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut builder = fmt.debug_struct("tau_engine::Error");
builder.field("kind", &self.inner.kind);
if let Some(ref source) = self.inner.source {
builder.field("source", source);
}
builder.finish()
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let desc = match self.inner.kind {
Kind::Parse(Parse::InvalidIdentifier) => {
"an invalid identifier was encountered during parsing"
}
Kind::Parse(Parse::InvalidExpression) => {
"an invalid expression was provided to the parser"
}
Kind::Parse(Parse::InvalidToken) => "an invalid token was encountered during parsing",
Kind::Parse(Parse::LedFollowing) => {
"an invalid expression was encountered following the LED during parsing"
}
Kind::Parse(Parse::LedPreceding) => {
"an invalid expression was encountered preceding the LED during parsing"
}
Kind::Rule => "an invalid rule was provided",
Kind::Token(Token::InvalidCharacter) => {
"an invalid character was encountered during tokenisation"
}
Kind::Token(Token::InvalidNumber) => {
"an invalid number was encountered during tokenisation"
}
Kind::Validation => "failed to validate rule",
};
if let Some(ref source) = self.inner.source {
write!(f, "{}: {}", desc, source)
} else {
f.write_str(desc)
}
}
}
impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
self.inner.source.as_ref().map(|e| &**e as _)
}
}
#[derive(Debug)]
pub enum Kind {
Parse(Parse),
Rule,
Token(Token),
Validation,
}
#[derive(Debug)]
pub enum Parse {
InvalidExpression,
InvalidIdentifier,
InvalidToken,
LedFollowing,
LedPreceding,
}
#[derive(Debug)]
pub enum Token {
InvalidCharacter,
InvalidNumber,
}
#[inline]
pub(crate) fn parse_invalid_expr<E: Into<Source>>(e: E) -> Error {
Error::new(Kind::Parse(Parse::InvalidExpression)).with(e)
}
#[inline]
pub(crate) fn parse_invalid_ident<E: Into<Source>>(e: E) -> Error {
Error::new(Kind::Parse(Parse::InvalidIdentifier)).with(e)
}
#[inline]
pub(crate) fn parse_invalid_token<E: Into<Source>>(e: E) -> Error {
Error::new(Kind::Parse(Parse::InvalidToken)).with(e)
}
#[inline]
pub(crate) fn parse_led_following<E: Into<Source>>(e: E) -> Error {
Error::new(Kind::Parse(Parse::LedFollowing)).with(e)
}
#[inline]
pub(crate) fn parse_led_preceding<E: Into<Source>>(e: E) -> Error {
Error::new(Kind::Parse(Parse::LedPreceding)).with(e)
}
#[inline]
pub(crate) fn rule_invalid<E: Into<Source>>(e: E) -> Error {
Error::new(Kind::Rule).with(e)
}
#[inline]
pub(crate) fn token_invalid_char<E: Into<Source>>(e: E) -> Error {
Error::new(Kind::Token(Token::InvalidCharacter)).with(e)
}
#[inline]
pub(crate) fn token_invalid_num<E: Into<Source>>(e: E) -> Error {
Error::new(Kind::Token(Token::InvalidNumber)).with(e)
}