Skip to main content

expr/
error.rs

1use crate::Rule;
2use std::fmt::{self, Debug, Display};
3
4/// An error that can occur when parsing or evaluating an expr program
5//
6// `Display`, `Error` and the two `From`s are written out rather than derived: `Debug` below
7// already is, and a `derive` was the whole reason this crate pulled thiserror into every
8// dependent's build for one 20-line enum.
9pub enum Error {
10    PestError(Box<pest::error::Error<Rule>>),
11    ParseError(String),
12    ExprError(String),
13    #[cfg(feature = "regex")]
14    RegexError(regex::Error),
15    #[cfg(feature = "serde")]
16    DeserializeError(String),
17    #[cfg(feature = "serde")]
18    SerializeError(String),
19}
20
21impl Display for Error {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        match self {
24            // Transparent, as they were: a pest error already says where it is, and prefixing
25            // it would bury that.
26            Error::PestError(e) => Display::fmt(e, f),
27            #[cfg(feature = "regex")]
28            Error::RegexError(e) => Display::fmt(e, f),
29            Error::ParseError(e) | Error::ExprError(e) => f.write_str(e),
30            #[cfg(feature = "serde")]
31            Error::DeserializeError(e) | Error::SerializeError(e) => f.write_str(e),
32        }
33    }
34}
35
36impl std::error::Error for Error {
37    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
38        match self {
39            Error::PestError(e) => Some(e),
40            #[cfg(feature = "regex")]
41            Error::RegexError(e) => Some(e),
42            _ => None,
43        }
44    }
45}
46
47impl From<Box<pest::error::Error<Rule>>> for Error {
48    fn from(err: Box<pest::error::Error<Rule>>) -> Self {
49        Error::PestError(err)
50    }
51}
52
53#[cfg(feature = "regex")]
54impl From<regex::Error> for Error {
55    fn from(err: regex::Error) -> Self {
56        Error::RegexError(err)
57    }
58}
59
60impl From<String> for Error {
61    fn from(s: String) -> Self {
62        Error::ExprError(s)
63    }
64}
65
66impl Debug for Error {
67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        match self {
69            Error::PestError(e) => write!(f, "PestError: {}", e),
70            Error::ParseError(e) => write!(f, "ParseError: {}", e),
71            Error::ExprError(e) => write!(f, "ExprError: {}", e),
72            #[cfg(feature = "regex")]
73            Error::RegexError(e) => write!(f, "RegexError: {}", e),
74            #[cfg(feature = "serde")]
75            Error::DeserializeError(e) => write!(f, "DeserializeError: {}", e),
76            #[cfg(feature = "serde")]
77            Error::SerializeError(e) => write!(f, "SerializeError: {}", e),
78        }
79    }
80}
81
82pub type Result<T> = std::result::Result<T, Error>;
83
84#[macro_export]
85macro_rules! bail {
86    ($($arg:tt)*) => {
87        return Err($crate::Error::ExprError(format!($($arg)*)))
88    };
89}