use std::fmt;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub enum Error {
NotFound(String),
Duplicate(String),
InvalidTriple(String),
Storage(String),
Serialization(String),
Query(String),
Index(String),
Io(std::io::Error),
Config(String),
BackendUnavailable(String),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotFound(msg) => write!(f, "not found: {}", msg),
Self::Duplicate(msg) => write!(f, "duplicate: {}", msg),
Self::InvalidTriple(msg) => write!(f, "invalid triple: {}", msg),
Self::Storage(msg) => write!(f, "storage error: {}", msg),
Self::Serialization(msg) => write!(f, "serialization error: {}", msg),
Self::Query(msg) => write!(f, "query error: {}", msg),
Self::Index(msg) => write!(f, "index error: {}", msg),
Self::Io(err) => write!(f, "I/O error: {}", err),
Self::Config(msg) => write!(f, "config error: {}", msg),
Self::BackendUnavailable(msg) => write!(f, "backend unavailable: {}", msg),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Io(err) => Some(err),
_ => None,
}
}
}
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self {
Self::Io(err)
}
}
impl From<bincode::error::EncodeError> for Error {
fn from(err: bincode::error::EncodeError) -> Self {
Self::Serialization(err.to_string())
}
}
impl From<bincode::error::DecodeError> for Error {
fn from(err: bincode::error::DecodeError) -> Self {
Self::Serialization(err.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = Error::NotFound("triple xyz".to_string());
assert!(err.to_string().contains("not found"));
assert!(err.to_string().contains("xyz"));
}
#[test]
fn test_error_from_io() {
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
let err: Error = io_err.into();
assert!(matches!(err, Error::Io(_)));
}
}