1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use std::error::Error as StdError;
use std::fmt;

#[macro_export]
macro_rules! error
{
    ( $err_type:ident, $msg:literal ) =>
    {
        {
            Error::$err_type(String::from($msg))
        }
    };
    ( $err_type:ident, $msg:literal $(, $x:expr)+) =>
    {
        {
            Error::$err_type(format!($msg $(, $x)+))
        }
    };
}

// Construct a RuntimeError
#[macro_export]
macro_rules! rterr
{
    ($msg:literal $(, $x:expr)*) =>
    {
        error!(RuntimeError, $msg $(, $x)*)
    };
}

// Construct an XMLError
#[macro_export]
macro_rules! xmlerr
{
    ($msg:literal $(, $x:expr)*) =>
    {
        error!(XMLError, $msg $(, $x)*)
    };
}

#[derive(Debug, Clone)]
pub enum Error
{
    /// An error from the underlying data source. This could be a
    /// database connection issue, or disk I/O failure, or invalid
    /// data from the data source, etc. This is not a “logic error”
    /// such as an error from generating SQL statement due to invalid
    /// backlinks.
    RuntimeError(String),
    XMLError(String),
}

impl fmt::Display for Error
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
    {
        match self
        {
            Error::RuntimeError(msg) => write!(f, "Runtime error: {}", msg),
            Error::XMLError(msg) => write!(f, "XML error: {}", msg),
        }
    }
}

impl StdError for Error
{
    fn source(&self) -> Option<&(dyn StdError + 'static)> {None}
}