pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub enum Error {
CapacityExceeded {
current: usize,
limit: usize,
resource: String,
},
NotFound(String),
InvalidQuery(String),
Serialization(String),
Storage(String),
Consolidation(String),
Config(String),
Internal(String),
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::CapacityExceeded {
current,
limit,
resource,
} => {
write!(
f,
"{} capacity exceeded: {} / {} limit",
resource, current, limit
)
}
Error::NotFound(id) => write!(f, "Memory not found: {}", id),
Error::InvalidQuery(msg) => write!(f, "Invalid query: {}", msg),
Error::Serialization(msg) => write!(f, "Serialization error: {}", msg),
Error::Storage(msg) => write!(f, "Storage error: {}", msg),
Error::Consolidation(msg) => write!(f, "Consolidation error: {}", msg),
Error::Config(msg) => write!(f, "Configuration error: {}", msg),
Error::Internal(msg) => write!(f, "Internal error: {}", msg),
}
}
}
impl std::error::Error for Error {}
impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Self {
Error::Serialization(e.to_string())
}
}
impl Error {
pub fn is_recoverable(&self) -> bool {
matches!(
self,
Error::CapacityExceeded { .. } | Error::NotFound(_) | Error::InvalidQuery(_)
)
}
pub fn capacity(resource: &str, current: usize, limit: usize) -> Self {
Error::CapacityExceeded {
current,
limit,
resource: resource.to_string(),
}
}
pub fn not_found(id: &str) -> Self {
Error::NotFound(id.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = Error::capacity("STM", 100, 50);
assert!(err.to_string().contains("capacity exceeded"));
}
#[test]
fn test_error_recoverable() {
assert!(Error::not_found("test").is_recoverable());
assert!(!Error::Internal("test".to_string()).is_recoverable());
}
}