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 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
102pub 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}