use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("Database error: {0}")]
Database(#[from] rusqlite::Error),
#[error("HTTP error: {0}")]
Http(#[from] reqwest::Error),
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error("Configuration error: {0}")]
Config(String),
#[error("Embedding error: {0}")]
Embedding(String),
#[error("Not found: {0}")]
NotFound(String),
#[error("Invalid input: {0}")]
InvalidInput(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Rate limit exceeded: retry after {retry_after_secs} seconds")]
RateLimit { retry_after_secs: u64 },
#[error("Authentication error: {0}")]
Auth(String),
#[error("Vector dimension mismatch: expected {expected}, got {actual}")]
DimensionMismatch { expected: usize, actual: usize },
#[error("Operation timed out after {0} seconds")]
Timeout(u64),
#[error("Internal error: {0}")]
Internal(String),
}
pub type Result<T> = std::result::Result<T, Error>;
impl Error {
pub fn is_retryable(&self) -> bool {
matches!(
self,
Error::Http(_) | Error::RateLimit { .. } | Error::Timeout(_)
)
}
pub fn config(msg: impl Into<String>) -> Self {
Error::Config(msg.into())
}
pub fn embedding(msg: impl Into<String>) -> Self {
Error::Embedding(msg.into())
}
pub fn not_found(msg: impl Into<String>) -> Self {
Error::NotFound(msg.into())
}
pub fn invalid_input(msg: impl Into<String>) -> Self {
Error::InvalidInput(msg.into())
}
pub fn internal(msg: impl Into<String>) -> Self {
Error::Internal(msg.into())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = Error::config("missing API key");
assert_eq!(err.to_string(), "Configuration error: missing API key");
}
#[test]
fn test_retryable() {
assert!(Error::RateLimit { retry_after_secs: 5 }.is_retryable());
assert!(Error::Timeout(30).is_retryable());
assert!(!Error::config("test").is_retryable());
assert!(!Error::NotFound("test".into()).is_retryable());
}
#[test]
fn test_dimension_mismatch() {
let err = Error::DimensionMismatch {
expected: 256,
actual: 384,
};
assert_eq!(
err.to_string(),
"Vector dimension mismatch: expected 256, got 384"
);
}
}