use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("configuration error: {0}")]
Config(String),
#[error("storage error: {0}")]
Storage(#[from] manifoldb_storage::engine::StorageError),
#[error("transaction error: {0}")]
Transaction(#[from] manifoldb_core::TransactionError),
#[error("parse error: {0}")]
Parse(String),
#[error("execution error: {0}")]
Execution(String),
#[error("failed to open database: {0}")]
Open(String),
#[error("invalid parameter: {0}")]
InvalidParameter(String),
#[error("type error: {0}")]
Type(String),
#[error("database is closed")]
Closed,
#[error("internal lock poisoned: {0}")]
LockPoisoned(String),
#[error("vector error: {0}")]
Vector(String),
#[error("bulk operation error: {0}")]
BulkOperation(String),
#[error("entity not found: {0}")]
EntityNotFound(manifoldb_core::EntityId),
#[error("invalid entity reference in edge: {0}")]
InvalidEntityReference(manifoldb_core::EntityId),
#[error("dimension mismatch for vector '{vector_name}': expected {expected}, got {actual}")]
DimensionMismatch {
vector_name: String,
expected: usize,
actual: usize,
},
#[error("invalid input: {0}")]
InvalidInput(String),
#[error("collection error: {0}")]
Collection(String),
#[error("serialization error: {0}")]
Serialization(String),
#[error("index error: {0}")]
Index(String),
}
impl Error {
#[must_use]
pub const fn is_recoverable(&self) -> bool {
matches!(
self,
Self::Parse(_)
| Self::InvalidParameter(_)
| Self::Type(_)
| Self::Execution(_)
| Self::Vector(_)
| Self::BulkOperation(_)
)
}
#[must_use]
pub const fn is_transaction_error(&self) -> bool {
matches!(self, Self::Transaction(_))
}
#[must_use]
pub const fn is_storage_error(&self) -> bool {
matches!(self, Self::Storage(_))
}
#[must_use]
pub fn parse(msg: impl Into<String>) -> Self {
Self::Parse(msg.into())
}
#[must_use]
pub fn execution(msg: impl Into<String>) -> Self {
Self::Execution(msg.into())
}
#[must_use]
pub fn config(msg: impl Into<String>) -> Self {
Self::Config(msg.into())
}
#[must_use]
pub fn lock_poisoned(msg: impl Into<String>) -> Self {
Self::LockPoisoned(msg.into())
}
#[must_use]
pub fn vector(msg: impl Into<String>) -> Self {
Self::Vector(msg.into())
}
#[must_use]
pub fn bulk_operation(msg: impl Into<String>) -> Self {
Self::BulkOperation(msg.into())
}
}
impl From<manifoldb_query::ParseError> for Error {
fn from(err: manifoldb_query::ParseError) -> Self {
Self::Parse(err.to_string())
}
}
pub type Result<T> = std::result::Result<T, Error>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_is_recoverable() {
assert!(Error::Parse("test".to_string()).is_recoverable());
assert!(Error::InvalidParameter("test".to_string()).is_recoverable());
assert!(Error::Type("test".to_string()).is_recoverable());
assert!(Error::Execution("test".to_string()).is_recoverable());
assert!(!Error::Open("test".to_string()).is_recoverable());
assert!(!Error::Config("test".to_string()).is_recoverable());
assert!(!Error::Closed.is_recoverable());
}
#[test]
fn test_error_display() {
let err = Error::parse("unexpected token");
assert_eq!(err.to_string(), "parse error: unexpected token");
let err = Error::execution("query timeout");
assert_eq!(err.to_string(), "execution error: query timeout");
}
}