use color_eyre::eyre::Report;
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum ErrorCode {
InternalError,
IoError,
StorageError,
SerializationError,
CollectionNotFound,
CollectionAlreadyExists,
UniqueConstraintViolation,
ProtocolError,
InvalidQuery,
InvalidOperation,
InvalidInput,
NotFound,
InvalidKey,
InvalidValue,
InvalidDefinition,
QueryError,
SchemaError,
TypeError,
UndefinedVariable,
ValidationError,
SecurityError,
Timeout,
FilterParseError,
}
#[derive(Debug)]
pub struct AqlError {
pub code: ErrorCode,
pub message: String,
pub source: Option<Report>,
pub line: Option<usize>,
pub column: Option<usize>,
}
impl AqlError {
pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
Self {
code,
message: message.into(),
source: None,
line: None,
column: None,
}
}
pub fn with_location(mut self, line: usize, column: usize) -> Self {
self.line = Some(line);
self.column = Some(column);
self
}
pub fn from_error<E>(code: ErrorCode, message: impl Into<String>, err: E) -> Self
where
E: Into<Report>,
{
Self {
code,
message: message.into(),
source: Some(err.into()),
line: None,
column: None,
}
}
pub fn invalid_operation(msg: impl Into<String>) -> Self {
Self::new(ErrorCode::InvalidOperation, msg)
}
pub fn schema_error(msg: impl Into<String>) -> Self {
Self::new(ErrorCode::SchemaError, msg)
}
}
impl fmt::Display for AqlError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let (Some(line), Some(col)) = (self.line, self.column) {
write!(
f,
"[{:?}] {} (line {}, col {})",
self.code, self.message, line, col
)
} else {
write!(f, "[{:?}] {}", self.code, self.message)
}
}
}
impl std::error::Error for AqlError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.source
.as_ref()
.map(|r| r.as_ref() as &(dyn std::error::Error + 'static))
}
}
pub type Result<T> = std::result::Result<T, AqlError>;
impl From<std::io::Error> for AqlError {
fn from(err: std::io::Error) -> Self {
Self::from_error(ErrorCode::IoError, "IO Error", err)
}
}
impl From<sled::Error> for AqlError {
fn from(err: sled::Error) -> Self {
Self::from_error(ErrorCode::StorageError, "Storage Error", err)
}
}
impl From<serde_json::Error> for AqlError {
fn from(err: serde_json::Error) -> Self {
Self::from_error(ErrorCode::SerializationError, "Serialization Error", err)
}
}
impl From<bincode::Error> for AqlError {
fn from(err: bincode::Error) -> Self {
Self::from_error(ErrorCode::SerializationError, "Bincode Error", err)
}
}
impl From<std::time::SystemTimeError> for AqlError {
fn from(err: std::time::SystemTimeError) -> Self {
Self::from_error(ErrorCode::InternalError, "System Time Error", err)
}
}
impl From<zip::result::ZipError> for AqlError {
fn from(err: zip::result::ZipError) -> Self {
Self::from_error(ErrorCode::InternalError, "Zip Error", err)
}
}
impl From<csv::Error> for AqlError {
fn from(err: csv::Error) -> Self {
Self::from_error(ErrorCode::InternalError, "CSV Error", err)
}
}