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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! Error types for the `dbgen` library.

use crate::parser::Function;
use failure::{Backtrace, Context, Fail};
use std::fmt;

/// Kinds of errors produced by the `dbgen` library.
#[derive(Fail, Debug, Clone, PartialEq, Eq)]
//#[non_exhaustive]
pub enum ErrorKind {
    /// Failed to parse template.
    #[fail(display = "failed to parse template")]
    ParseTemplate,

    /// Unknown SQL function.
    #[fail(display = "unknown function '{}'", 0)]
    UnknownFunction(
        /// The name of the unknown SQL function.
        String,
    ),

    /// Integer is too big.
    #[fail(display = "integer '{}' is too big", 0)]
    IntegerOverflow(
        /// The string representation of the expression that produced the overflow.
        String,
    ),

    /// Not enough arguments provided to the SQL function.
    #[fail(display = "not enough arguments to function {}", 0)]
    NotEnoughArguments(
        /// The SQL function causing the error.
        Function,
    ),

    /// Invalid regex.
    #[fail(display = "invalid regex {}", 0)]
    InvalidRegex(
        /// The regex pattern.
        String,
    ),

    /// Unknown regex flag.
    #[fail(display = "unknown regex flag {}", 0)]
    UnknownRegexFlag(
        /// The regex flag.
        char,
    ),

    /// Unsupported regex element (e.g. `\b`)
    #[fail(display = "unsupported regex element: '{}'", 0)]
    UnsupportedRegexElement(
        /// The regex element.
        String,
    ),

    /// Invalid argument type.
    ///
    /// If this error is encountered during compilation phase, the error will be
    /// ignored and the function will be kept in raw form.
    #[fail(
        display = "invalid argument type: in function {}, argument #{} should be a {}",
        name, index, expected
    )]
    InvalidArgumentType {
        /// The SQL function causing the error.
        name: Function,
        /// Argument index.
        index: usize,
        /// The expected type.
        expected: &'static str,
    },

    /// Invalid arguments.
    #[fail(display = "invalid arguments: in function {}, assertion failed: {}", name, cause)]
    InvalidArguments {
        /// The SQL function causing the error.
        name: Function,
        /// Cause of the error.
        cause: String,
    },

    /// The timestamp string is invalid
    #[fail(display = "invalid timestamp '{}'", 0)]
    InvalidTimestampString(
        /// The literal which is in the wrong format.
        String,
    ),

    /// Failed to write the SQL `CREATE TABLE` schema file.
    #[fail(display = "failed to write SQL schema")]
    WriteSqlSchema,

    /// Failed to write the SQL data file.
    #[fail(display = "failed to write SQL data")]
    WriteSqlData,

    /// Failed to write an SQL value.
    #[fail(display = "failed to write SQL value")]
    WriteSqlValue,

    #[doc(hidden)]
    #[fail(display = "(placeholder)")]
    __NonExhaustive,
}

/// An error produced by the `dbgen` library.
#[derive(Debug)]
pub struct Error {
    inner: Context<ErrorKind>,
}

impl Fail for Error {
    fn cause(&self) -> Option<&dyn Fail> {
        self.inner.cause()
    }

    fn backtrace(&self) -> Option<&Backtrace> {
        self.inner.backtrace()
    }
}

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

impl Error {
    /// The kind of this error.
    pub fn kind(&self) -> &ErrorKind {
        self.inner.get_context()
    }
}

impl From<ErrorKind> for Error {
    fn from(kind: ErrorKind) -> Self {
        Self {
            inner: Context::new(kind),
        }
    }
}

impl From<Context<ErrorKind>> for Error {
    fn from(inner: Context<ErrorKind>) -> Self {
        Self { inner }
    }
}