1use core::fmt;
2
3#[derive(Clone, Debug)]
5pub struct Error {
6 pub code: ErrorCode,
7 pub extended: Option<i32>,
8 pub message: Option<String>,
9}
10
11pub type Result<T> = core::result::Result<T, Error>;
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq)]
16pub enum ErrorCode {
17 Ok,
18 Error,
19 Abort,
20 Busy,
21 NoMem,
22 Interrupt,
23 NotFound,
24 CantOpen,
25 Misuse,
26 Row,
27 Done,
28 FeatureUnavailable,
29 Unknown(i32),
30}
31
32impl ErrorCode {
33 pub const fn from_code(code: i32) -> ErrorCode {
34 match code {
35 0 => ErrorCode::Ok,
36 1 => ErrorCode::Error,
37 4 => ErrorCode::Abort,
38 5 => ErrorCode::Busy,
39 7 => ErrorCode::NoMem,
40 9 => ErrorCode::Interrupt,
41 12 => ErrorCode::NotFound,
42 14 => ErrorCode::CantOpen,
43 21 => ErrorCode::Misuse,
44 100 => ErrorCode::Row,
45 101 => ErrorCode::Done,
46 other => ErrorCode::Unknown(other),
47 }
48 }
49
50 pub const fn code(self) -> Option<i32> {
51 match self {
52 ErrorCode::Ok => Some(0),
53 ErrorCode::Error => Some(1),
54 ErrorCode::Abort => Some(4),
55 ErrorCode::Busy => Some(5),
56 ErrorCode::NoMem => Some(7),
57 ErrorCode::Interrupt => Some(9),
58 ErrorCode::NotFound => Some(12),
59 ErrorCode::CantOpen => Some(14),
60 ErrorCode::Misuse => Some(21),
61 ErrorCode::Row => Some(100),
62 ErrorCode::Done => Some(101),
63 ErrorCode::FeatureUnavailable => None,
64 ErrorCode::Unknown(code) => Some(code),
65 }
66 }
67}
68
69impl Error {
70 pub fn new(code: ErrorCode) -> Self {
71 Self { code, extended: None, message: None }
72 }
73
74 pub fn with_message(code: ErrorCode, message: impl Into<String>) -> Self {
75 Self { code, extended: None, message: Some(message.into()) }
76 }
77
78 pub fn from_code(code: i32, message: Option<String>, extended: Option<i32>) -> Self {
79 Self { code: ErrorCode::from_code(code), extended, message }
80 }
81
82 pub fn feature_unavailable(msg: &'static str) -> Self {
83 Self { code: ErrorCode::FeatureUnavailable, extended: None, message: Some(msg.into()) }
84 }
85}
86
87impl fmt::Display for Error {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 match (self.code, &self.message) {
90 (_, Some(msg)) => write!(f, "{}", msg),
91 (ErrorCode::Unknown(code), None) => write!(f, "sqlite error code {}", code),
92 (ErrorCode::FeatureUnavailable, None) => write!(f, "feature unavailable"),
93 (code, None) => write!(f, "sqlite error {:?}", code),
94 }
95 }
96}
97
98impl std::error::Error for Error {}
99
100#[cfg(test)]
101mod tests {
102 use super::{Error, ErrorCode};
103
104 #[test]
105 fn error_code_mapping() {
106 assert_eq!(ErrorCode::from_code(0), ErrorCode::Ok);
107 assert_eq!(ErrorCode::from_code(14), ErrorCode::CantOpen);
108 assert_eq!(ErrorCode::from_code(999), ErrorCode::Unknown(999));
109 }
110
111 #[test]
112 fn feature_unavailable_message() {
113 let err = Error::feature_unavailable("missing");
114 assert_eq!(err.code, ErrorCode::FeatureUnavailable);
115 assert_eq!(err.message.as_deref(), Some("missing"));
116 }
117}