sqlite_tiny/
error.rs

1//! Implements the crate's error type
2
3use std::{
4    backtrace::{Backtrace, BacktraceStatus},
5    fmt::{self, Display, Formatter},
6};
7
8/// Creates a new error
9#[macro_export]
10macro_rules! err {
11    (with: $error:expr, $($arg:tt)*) => {{
12        let error = format!($($arg)*);
13        let source = Box::new($error);
14        $crate::error::Error::new(error, Some(source))
15    }};
16    ($($arg:tt)*) => {{
17        let error = format!($($arg)*);
18        $crate::error::Error::new(error, None)
19    }};
20}
21
22/// The crates error type
23#[derive(Debug)]
24pub struct Error {
25    /// The error description
26    pub error: String,
27    /// The underlying error
28    pub source: Option<Box<dyn std::error::Error + Send>>,
29    /// The backtrace
30    pub backtrace: Backtrace,
31}
32impl Error {
33    /// Creates a new error and captures a backtrace
34    pub fn new(error: String, source: Option<Box<dyn std::error::Error + Send>>) -> Self {
35        let backtrace = Backtrace::capture();
36        Self { error, source, backtrace }
37    }
38
39    /// Whether the error has captured a backtrace or not
40    pub fn has_backtrace(&self) -> bool {
41        self.backtrace.status() == BacktraceStatus::Captured
42    }
43}
44impl Display for Error {
45    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
46        // Print the error
47        writeln!(f, "{}", self.error)?;
48
49        // Print the source
50        if let Some(source) = &self.source {
51            writeln!(f, " caused by: {source}")?;
52        }
53        Ok(())
54    }
55}
56impl std::error::Error for Error {
57    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
58        // Do some type gymnastics to get the `Send` out of the typesystem, because it breaks a direct conversion
59        #[allow(clippy::borrowed_box, reason = "Type gymnastics to remove the `Send`")]
60        let source: &Box<dyn std::error::Error + Send> = self.source.as_ref()?;
61        let source: &dyn std::error::Error = source.as_ref();
62        Some(source)
63    }
64}