Skip to main content

aurora_db/
error.rs

1use color_eyre::eyre::Report;
2use serde::{Deserialize, Serialize};
3use std::fmt;
4
5#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
6pub enum ErrorCode {
7    InternalError,
8    IoError,
9    StorageError,
10    SerializationError,
11    CollectionNotFound,
12    CollectionAlreadyExists,
13    UniqueConstraintViolation,
14    ProtocolError,
15    InvalidOperation,
16    InvalidInput,
17    NotFound,
18    InvalidKey,
19    InvalidValue,
20    InvalidDefinition,
21    QueryError,
22    SchemaError,
23    TypeError,
24    UndefinedVariable,
25    ValidationError,
26    SecurityError,
27    Timeout,
28    FilterParseError,
29}
30
31#[derive(Debug)]
32pub struct AqlError {
33    pub code: ErrorCode,
34    pub message: String,
35    pub source: Option<Report>,
36    pub line: Option<usize>,
37    pub column: Option<usize>,
38}
39
40impl AqlError {
41    pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
42        Self {
43            code,
44            message: message.into(),
45            source: None,
46            line: None,
47            column: None,
48        }
49    }
50
51    pub fn with_location(mut self, line: usize, column: usize) -> Self {
52        self.line = Some(line);
53        self.column = Some(column);
54        self
55    }
56
57    pub fn from_error<E>(code: ErrorCode, message: impl Into<String>, err: E) -> Self
58    where
59        E: Into<Report>,
60    {
61        Self {
62            code,
63            message: message.into(),
64            source: Some(err.into()),
65            line: None,
66            column: None,
67        }
68    }
69
70    // Convenience constructors
71    pub fn invalid_operation(msg: impl Into<String>) -> Self {
72        Self::new(ErrorCode::InvalidOperation, msg)
73    }
74
75    pub fn schema_error(msg: impl Into<String>) -> Self {
76        Self::new(ErrorCode::SchemaError, msg)
77    }
78}
79
80impl fmt::Display for AqlError {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        if let (Some(line), Some(col)) = (self.line, self.column) {
83            write!(
84                f,
85                "[{:?}] {} (line {}, col {})",
86                self.code, self.message, line, col
87            )
88        } else {
89            write!(f, "[{:?}] {}", self.code, self.message)
90        }
91    }
92}
93
94impl std::error::Error for AqlError {
95    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
96        self.source
97            .as_ref()
98            .map(|r| r.as_ref() as &(dyn std::error::Error + 'static))
99    }
100}
101
102// Result alias
103pub type Result<T> = std::result::Result<T, AqlError>;
104
105impl From<std::io::Error> for AqlError {
106    fn from(err: std::io::Error) -> Self {
107        Self::from_error(ErrorCode::IoError, "IO Error", err)
108    }
109}
110
111impl From<sled::Error> for AqlError {
112    fn from(err: sled::Error) -> Self {
113        Self::from_error(ErrorCode::StorageError, "Storage Error", err)
114    }
115}
116
117impl From<serde_json::Error> for AqlError {
118    fn from(err: serde_json::Error) -> Self {
119        Self::from_error(ErrorCode::SerializationError, "Serialization Error", err)
120    }
121}
122
123impl From<bincode::Error> for AqlError {
124    fn from(err: bincode::Error) -> Self {
125        Self::from_error(ErrorCode::SerializationError, "Bincode Error", err)
126    }
127}
128
129impl From<std::time::SystemTimeError> for AqlError {
130    fn from(err: std::time::SystemTimeError) -> Self {
131        Self::from_error(ErrorCode::InternalError, "System Time Error", err)
132    }
133}
134
135impl From<zip::result::ZipError> for AqlError {
136    fn from(err: zip::result::ZipError) -> Self {
137        Self::from_error(ErrorCode::InternalError, "Zip Error", err)
138    }
139}
140
141impl From<csv::Error> for AqlError {
142    fn from(err: csv::Error) -> Self {
143        Self::from_error(ErrorCode::InternalError, "CSV Error", err)
144    }
145}