use crate::prelude::*;
#[derive(Debug, ThisError)]
pub struct Error {
kind: Kind,
}
impl Error {
#[must_use]
pub fn kind(&self) -> &Kind {
&self.kind
}
pub(crate) fn new(kind: Kind) -> Self {
Self { kind }
}
pub(crate) fn file_pattern(path: PathBuf) -> Self {
Self::new(Kind::WrongFileNamePattern(path))
}
pub(crate) fn validation(kind: ValidationErrorKind, cause: impl Into<String>) -> Self {
let cause = cause.into();
Self::new(Kind::Validation { kind, cause })
}
pub(crate) fn uninitialized() -> Self {
Self::new(Kind::Uninitialized)
}
pub(crate) fn active_blob_not_set() -> Self {
Self::new(Kind::ActiveBlobNotSet)
}
pub(crate) fn active_blob_doesnt_exist() -> Self {
Self::new(Kind::ActiveBlobDoesntExist)
}
pub(crate) fn active_blob_already_exists() -> Self {
Self::new(Kind::ActiveBlobExists)
}
#[allow(dead_code)]
pub(crate) fn io(s: String) -> Self {
Self::new(Kind::IO(s))
}
pub(crate) fn bincode(s: String) -> Self {
Self::new(Kind::Bincode(s))
}
pub(crate) fn file_unavailable(kind: IOErrorKind) -> Self {
Self::new(Kind::FileUnavailable(kind))
}
pub(crate) fn work_dir_unavailable(
path: impl AsRef<Path>,
msg: String,
io_err_kind: IOErrorKind,
) -> Self {
Self::new(Kind::WorkDirUnavailable {
path: path.as_ref().into(),
msg,
io_err_kind,
})
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
Debug::fmt(&self.kind, f)
}
}
impl From<Kind> for Error {
#[must_use]
fn from(kind: Kind) -> Self {
Self { kind }
}
}
impl From<bincode::Error> for Error {
fn from(value: bincode::Error) -> Self {
Self {
kind: Kind::Bincode(format!("Serialization/deserialization error: {}", value))
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Kind {
ActiveBlobNotSet,
WrongConfig,
Uninitialized,
WorkDirInUse,
WorkDirUnavailable {
path: PathBuf,
msg: String,
io_err_kind: IOErrorKind,
},
FileUnavailable(IOErrorKind),
KeySizeMismatch,
ActiveBlobDoesntExist,
ActiveBlobExists,
RecordExists,
EmptyIndexBunch,
Index(String),
Bincode(String),
IO(String),
WrongFileNamePattern(PathBuf),
Conversion(String),
Validation {
kind: ValidationErrorKind,
cause: String,
},
Other,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ValidationErrorKind {
BlobKeySize,
BlobMagicByte,
BlobVersion,
IndexChecksum,
IndexVersion,
IndexKeySize,
IndexMagicByte,
RecordDataChecksum,
RecordHeaderChecksum,
RecordMagicByte,
IndexBlobSize,
IndexNotWritten,
}
pub trait AsPearlError {
fn as_pearl_error(&self) -> Option<&Error>;
}
impl AsPearlError for anyhow::Error {
fn as_pearl_error(&self) -> Option<&Error> {
self.downcast_ref()
}
}
const BINCODE_ON_UNEXPECTED_EOF_ERROR_TEXT: &'static str = "Can't read whole buffer, required for deserialization due to unexpected end of file";
pub(crate) trait IntoBincodeIfUnexpectedEofTrait {
fn into_bincode_if_unexpected_eof(self) -> anyhow::Error;
}
impl IntoBincodeIfUnexpectedEofTrait for IOError {
fn into_bincode_if_unexpected_eof(self) -> anyhow::Error {
if self.kind() == IOErrorKind::UnexpectedEof {
Error::bincode(BINCODE_ON_UNEXPECTED_EOF_ERROR_TEXT.to_string()).into()
} else {
self.into()
}
}
}
impl IntoBincodeIfUnexpectedEofTrait for anyhow::Error {
fn into_bincode_if_unexpected_eof(self) -> anyhow::Error {
if let Some(io_error) = self.downcast_ref::<IOError>() {
if io_error.kind() == IOErrorKind::UnexpectedEof {
return Error::bincode(BINCODE_ON_UNEXPECTED_EOF_ERROR_TEXT.to_string()).into();
}
}
return self;
}
}