use std::{fmt, io};
use serde::{Deserialize, Serialize};
use tantivy::directory::error::{OpenDirectoryError, OpenReadError};
use thiserror::Error;
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
pub enum StorageErrorKind {
DoesNotExist,
Unauthorized,
Service,
InternalError,
Io,
}
#[allow(missing_docs)]
#[derive(Error, Debug, Serialize, Deserialize, Clone)]
pub enum StorageResolverError {
#[error("Invalid format for URI: required: `{message}`")]
InvalidUri { message: String },
#[error("Unsupported protocol: `{protocol}`")]
ProtocolUnsupported { protocol: String },
#[error("Failed to open storage {kind:?}: {message}.")]
FailedToOpenStorage {
kind: crate::StorageErrorKind,
message: String,
},
}
impl StorageErrorKind {
pub fn with_error<E>(self, source: E) -> StorageError
where anyhow::Error: From<E> {
StorageError {
kind: self,
source: From::from(source),
}
}
}
impl From<StorageError> for io::Error {
fn from(storage_err: StorageError) -> Self {
let io_error_kind = match storage_err.kind() {
StorageErrorKind::DoesNotExist => io::ErrorKind::NotFound,
_ => io::ErrorKind::Other,
};
io::Error::new(io_error_kind, storage_err.source)
}
}
#[derive(Error, Debug)]
#[error("StorageError(kind={kind:?}, source={source})")]
#[allow(missing_docs)]
pub struct StorageError {
pub kind: StorageErrorKind,
#[source]
source: anyhow::Error,
}
pub type StorageResult<T> = Result<T, StorageError>;
impl StorageError {
pub fn add_context<C>(self, ctx: C) -> Self
where C: fmt::Display + Send + Sync + 'static {
StorageError {
kind: self.kind,
source: self.source.context(ctx),
}
}
pub fn kind(&self) -> StorageErrorKind {
self.kind
}
}
impl From<io::Error> for StorageError {
fn from(err: io::Error) -> StorageError {
match err.kind() {
io::ErrorKind::NotFound => StorageErrorKind::DoesNotExist.with_error(err),
_ => StorageErrorKind::Io.with_error(err),
}
}
}
impl From<OpenDirectoryError> for StorageError {
fn from(err: OpenDirectoryError) -> StorageError {
match err {
OpenDirectoryError::DoesNotExist(_) => StorageErrorKind::DoesNotExist.with_error(err),
_ => StorageErrorKind::Io.with_error(err),
}
}
}
impl From<OpenReadError> for StorageError {
fn from(err: OpenReadError) -> StorageError {
match err {
OpenReadError::FileDoesNotExist(_) => StorageErrorKind::DoesNotExist.with_error(err),
_ => StorageErrorKind::Io.with_error(err),
}
}
}