Skip to main content

sql_hummus/
error.rs

1/// Public-facing opaque error
2#[derive(Debug, thiserror::Error)]
3#[error(transparent)]
4pub struct Error(#[from] ErrorRepr);
5
6pub type Result<T> = std::result::Result<T, Error>;
7
8// FIXME: I'm not 100% about this error setup. If you have gdb, it's redundant. If you don't have gdb, it's better than nothing.
9// Unlike anyhow it's only safe Rust, and it's very simple, and it's my code.
10#[derive(Debug, thiserror::Error)]
11#[error("kind={kind}; cookies={cookies:?}")]
12struct ErrorRepr {
13    cookies: Vec<&'static str>,
14    #[source]
15    kind: ErrorKind,
16}
17
18#[derive(Debug, thiserror::Error)]
19pub(crate) enum ErrorKind {
20    #[error(transparent)]
21    FromPathBufError(#[from] camino::FromPathBufError),
22    #[error("IO error: {0}")]
23    Io(#[from] std::io::Error),
24    #[error("Error: {0}")]
25    Str(&'static str),
26    #[error("SQLite error: {0}")]
27    Sqlite(#[from] sql_peas::Error),
28    #[error("ULID decode error: {0}")]
29    UlidDecode(#[from] ulid::DecodeError),
30}
31
32impl From<&'static str> for ErrorKind {
33    fn from(s: &'static str) -> Self {
34        Self::Str(s)
35    }
36}
37
38impl<T> From<T> for Error
39where
40    ErrorKind: From<T>,
41{
42    fn from(value: T) -> Self {
43        ErrorRepr {
44            cookies: vec![],
45            kind: ErrorKind::from(value),
46        }
47        .into()
48    }
49}
50
51/// Just like `anyhow::Context` but simpler
52///
53/// "Type 'cookie', you idiot." -- The Plague, Hackers (film)
54pub(crate) trait Cookie<T> {
55    fn cookie(self, s: &'static str) -> Result<T>;
56}
57
58impl<T, E> Cookie<T> for std::result::Result<T, E>
59where
60    Error: From<E>,
61{
62    fn cookie(self, s: &'static str) -> Result<T> {
63        match self {
64            Ok(x) => Ok(x),
65            Err(e) => {
66                let mut e = Error::from(e);
67                e.0.cookies.push(s);
68                Err(e)
69            }
70        }
71    }
72}