use std::path::PathBuf;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum CodeSearchError {
#[error("Database error: {message}")]
Database {
message: String,
source: Option<anyhow::Error>,
},
#[error("I/O error: {path} - {message}")]
Io {
path: PathBuf,
message: String,
source: Option<anyhow::Error>,
},
#[error("Embedding error: {message}")]
Embedding { message: String },
#[error("Search error: {message}")]
Search { message: String },
#[error("Index error: {message}")]
Index { message: String },
#[error("Configuration error: {message}")]
Config { message: String },
#[error("MCP error: {message}")]
Mcp { message: String },
#[error("Parse error: {path} - {message}")]
Parse {
path: PathBuf,
message: String,
source: Option<anyhow::Error>,
},
#[error("Validation error: {message}")]
Validation { message: String },
}
impl CodeSearchError {
pub fn database(message: impl Into<String>) -> Self {
Self::Database {
message: message.into(),
source: None,
}
}
pub fn io(path: impl Into<PathBuf>, message: impl Into<String>) -> Self {
Self::Io {
path: path.into(),
message: message.into(),
source: None,
}
}
pub fn embedding(message: impl Into<String>) -> Self {
Self::Embedding {
message: message.into(),
}
}
pub fn search(message: impl Into<String>) -> Self {
Self::Search {
message: message.into(),
}
}
pub fn index(message: impl Into<String>) -> Self {
Self::Index {
message: message.into(),
}
}
pub fn config(message: impl Into<String>) -> Self {
Self::Config {
message: message.into(),
}
}
pub fn mcp(message: impl Into<String>) -> Self {
Self::Mcp {
message: message.into(),
}
}
pub fn parse(path: impl Into<PathBuf>, message: impl Into<String>) -> Self {
Self::Parse {
path: path.into(),
message: message.into(),
source: None,
}
}
pub fn validation(message: impl Into<String>) -> Self {
Self::Validation {
message: message.into(),
}
}
}
pub type Result<T> = std::result::Result<T, CodeSearchError>;
impl From<std::io::Error> for CodeSearchError {
fn from(err: std::io::Error) -> Self {
Self::Io {
path: PathBuf::new(),
message: err.to_string(),
source: None,
}
}
}
impl From<anyhow::Error> for CodeSearchError {
fn from(err: anyhow::Error) -> Self {
Self::Database {
message: err.to_string(),
source: Some(err),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_creation() {
let err = CodeSearchError::database("Test error");
assert!(err.to_string().contains("Database error"));
let err = CodeSearchError::validation("Invalid input");
assert!(err.to_string().contains("Validation error"));
}
#[test]
fn test_io_error() {
let path = PathBuf::from("/test/path");
let err = CodeSearchError::io(&path, "File not found");
assert!(err.to_string().contains("I/O error"));
assert!(err.to_string().contains("/test/path"));
}
}