use std::io;
use thiserror::Error;
pub type MemResult<T> = Result<T, MemError>;
#[derive(Error, Debug)]
#[allow(dead_code)]
pub enum MemError {
#[error("Storage error: {0}")]
Storage(String),
#[error("Embedding error: {0}")]
Embedding(String),
#[error("Retrieval error: {0}")]
Retrieval(String),
#[error("RAPTOR error: {0}")]
Raptor(String),
#[error("Indexing error: {0}")]
Indexing(String),
#[error("RAG error: {0}")]
Rag(String),
#[error("IO error: {0}")]
Io(#[from] io::Error),
#[error("Serialization error: {0}")]
Serialization(String),
#[error("Configuration error: {0}")]
Config(String),
#[error("Network error: {0}")]
Network(String),
#[error("Qdrant error: {0}")]
Qdrant(String),
#[error("Tantivy error: {0}")]
Tantivy(String),
#[error("Document not found: {0}")]
NotFound(String),
#[error("Invalid input: {0}")]
InvalidInput(String),
#[error("Hot memory error: {0}")]
HotMemory(String),
#[error("Cold memory error: {0}")]
ColdMemory(String),
#[error("WAL error: {0}")]
Wal(String),
#[error("Sync error: {0}")]
Sync(String),
#[error("Checksum mismatch: expected {expected}, got {actual}")]
ChecksumMismatch {
expected: u32,
actual: u32,
},
#[error("Recovery error: {0}")]
Recovery(String),
#[error("Capacity exceeded: {current} / {max}")]
CapacityExceeded {
current: usize,
max: usize,
},
}
impl From<serde_json::Error> for MemError {
fn from(err: serde_json::Error) -> Self {
MemError::Serialization(err.to_string())
}
}
impl From<reqwest::Error> for MemError {
fn from(err: reqwest::Error) -> Self {
MemError::Network(err.to_string())
}
}
impl MemError {
pub fn io(msg: impl Into<String>) -> Self {
MemError::Storage(msg.into())
}
pub fn storage(msg: impl Into<String>) -> Self {
MemError::Storage(msg.into())
}
pub fn embedding(msg: impl Into<String>) -> Self {
MemError::Embedding(msg.into())
}
pub fn retrieval(msg: impl Into<String>) -> Self {
MemError::Retrieval(msg.into())
}
pub fn qdrant(msg: impl Into<String>) -> Self {
MemError::Qdrant(msg.into())
}
pub fn config(msg: impl Into<String>) -> Self {
MemError::Config(msg.into())
}
pub fn not_found(msg: impl Into<String>) -> Self {
MemError::NotFound(msg.into())
}
pub fn parse(msg: impl Into<String>) -> Self {
MemError::Serialization(msg.into())
}
pub fn tantivy(msg: impl Into<String>) -> Self {
MemError::Tantivy(msg.into())
}
pub fn invalid_input(msg: impl Into<String>) -> Self {
MemError::InvalidInput(msg.into())
}
pub fn validation(msg: impl Into<String>) -> Self {
MemError::InvalidInput(msg.into())
}
pub fn network(msg: impl Into<String>) -> Self {
MemError::Network(msg.into())
}
pub fn raptor(msg: impl Into<String>) -> Self {
MemError::Raptor(msg.into())
}
pub fn rag(msg: impl Into<String>) -> Self {
MemError::Rag(msg.into())
}
pub fn indexing(msg: impl Into<String>) -> Self {
MemError::Indexing(msg.into())
}
pub fn query(msg: impl Into<String>) -> Self {
MemError::Retrieval(msg.into())
}
pub fn generation(msg: impl Into<String>) -> Self {
MemError::Retrieval(msg.into())
}
pub fn hot_memory(msg: impl Into<String>) -> Self {
MemError::HotMemory(msg.into())
}
pub fn cold_memory(msg: impl Into<String>) -> Self {
MemError::ColdMemory(msg.into())
}
pub fn wal(msg: impl Into<String>) -> Self {
MemError::Wal(msg.into())
}
pub fn sync(msg: impl Into<String>) -> Self {
MemError::Sync(msg.into())
}
pub fn checksum_mismatch(expected: u32, actual: u32) -> Self {
MemError::ChecksumMismatch { expected, actual }
}
pub fn recovery(msg: impl Into<String>) -> Self {
MemError::Recovery(msg.into())
}
pub fn capacity_exceeded(current: usize, max: usize) -> Self {
MemError::CapacityExceeded { current, max }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = MemError::Storage("connection failed".to_string());
assert_eq!(err.to_string(), "Storage error: connection failed");
}
#[test]
fn test_error_from_io() {
let io_err = io::Error::new(io::ErrorKind::NotFound, "file not found");
let mem_err: MemError = io_err.into();
assert!(matches!(mem_err, MemError::Io(_)));
}
#[test]
fn test_hot_memory_error() {
let err = MemError::hot_memory("cache eviction failed");
assert_eq!(err.to_string(), "Hot memory error: cache eviction failed");
}
#[test]
fn test_cold_memory_error() {
let err = MemError::cold_memory("disk write failed");
assert_eq!(err.to_string(), "Cold memory error: disk write failed");
}
#[test]
fn test_wal_error() {
let err = MemError::wal("log corruption detected");
assert_eq!(err.to_string(), "WAL error: log corruption detected");
}
#[test]
fn test_sync_error() {
let err = MemError::sync("hot-cold sync timeout");
assert_eq!(err.to_string(), "Sync error: hot-cold sync timeout");
}
#[test]
fn test_checksum_mismatch() {
let err = MemError::checksum_mismatch(0xDEADBEEF, 0xCAFEBABE);
assert_eq!(
err.to_string(),
"Checksum mismatch: expected 3735928559, got 3405691582"
);
}
#[test]
fn test_recovery_error() {
let err = MemError::recovery("WAL replay failed at entry 42");
assert_eq!(
err.to_string(),
"Recovery error: WAL replay failed at entry 42"
);
}
#[test]
fn test_capacity_exceeded() {
let err = MemError::capacity_exceeded(1500, 1000);
assert_eq!(err.to_string(), "Capacity exceeded: 1500 / 1000");
}
}