use std::path::{Path, PathBuf};
use thiserror::Error;
#[derive(Debug, Clone, PartialEq, Eq, Error)]
#[error("parse error: {0}")]
pub struct ParseError(String);
impl ParseError {
pub(crate) fn new(msg: impl Into<String>) -> Self {
ParseError(msg.into())
}
pub fn message(&self) -> &str {
&self.0
}
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum Error {
#[error(transparent)]
Parse(#[from] ParseError),
#[error("corpus {}", path.display())]
#[non_exhaustive]
Io {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("corpus {}: {reason}", path.display())]
#[non_exhaustive]
Corrupt { path: PathBuf, reason: String },
#[error("corpus {}: {reason}", path.display())]
#[non_exhaustive]
Unsupported { path: PathBuf, reason: String },
#[cfg(feature = "sqlite")]
#[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
#[error("corpus {}", path.display())]
#[non_exhaustive]
Sqlite {
path: PathBuf,
#[source]
source: Box<dyn std::error::Error + Send + Sync>,
},
}
pub type Result<T, E = Error> = std::result::Result<T, E>;
impl Error {
pub(crate) fn io(path: &Path, source: std::io::Error) -> Self {
Error::Io {
path: path.to_path_buf(),
source,
}
}
pub(crate) fn corrupt(path: &Path, reason: impl Into<String>) -> Self {
Error::Corrupt {
path: path.to_path_buf(),
reason: reason.into(),
}
}
pub(crate) fn unsupported(path: &Path, reason: impl Into<String>) -> Self {
Error::Unsupported {
path: path.to_path_buf(),
reason: reason.into(),
}
}
#[cfg(feature = "sqlite")]
pub(crate) fn sqlite(path: &Path, source: rusqlite::Error) -> Self {
Error::Sqlite {
path: path.to_path_buf(),
source: Box::new(source),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_a_well_behaved_error() {
fn assert_error<T: std::error::Error + Send + Sync + 'static>() {}
assert_error::<Error>();
assert_error::<ParseError>();
}
#[test]
fn display_names_the_path_and_source_carries_the_cause() {
let e = Error::io(
Path::new("/x/c.json"),
std::io::Error::from(std::io::ErrorKind::NotFound),
);
assert_eq!(e.to_string(), "corpus /x/c.json");
assert!(std::error::Error::source(&e).is_some());
}
}