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