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