use std::convert::Infallible;
use std::error::Error as StdError;
use std::fmt::Result as FmtResult;
use std::fmt::{Display, Formatter};
use std::result::Result as StdResult;
pub const WRONG_OFFSET: &str = "Wrong buffer offset detected";
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
Invalid {
desc: String,
source: Option<Box<dyn StdError + Send + Sync + 'static>>,
},
Read {
desc: String,
source: Option<Box<dyn StdError + Send + Sync + 'static>>,
},
Write {
desc: String,
source: Option<Box<dyn StdError + Send + Sync + 'static>>,
},
NotImplemented { desc: String },
Internal {
desc: String,
source: Option<Box<dyn StdError + Send + Sync + 'static>>,
},
}
impl Error {
pub fn invalid<T, C>(desc: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
Err(Error::Invalid {
desc: desc.to_string(),
source: None,
})
}
pub fn not_implemented<T, C>(desc: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
Err(Error::NotImplemented {
desc: desc.to_string(),
})
}
pub fn internal<T, C>(desc: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
Err(Error::Internal {
desc: desc.to_string(),
source: None,
})
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
match self {
Error::Invalid { desc, .. } => write!(f, "Invalid E57 content: {desc}"),
Error::Read { desc, .. } => write!(f, "Failed to read E57: {desc}"),
Error::Internal { desc, .. } => write!(f, "Internal error: {desc}"),
Error::NotImplemented { desc } => write!(f, "Not implemented: {desc}"),
Error::Write { desc, .. } => write!(f, "Failed to write E57: {desc}"),
}
}
}
impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self {
Error::Invalid { source, .. } => source
.as_ref()
.map(|s| s.as_ref() as &(dyn StdError + 'static)),
Error::Read { source, .. } => source
.as_ref()
.map(|s| s.as_ref() as &(dyn StdError + 'static)),
Error::Internal { source, .. } => source
.as_ref()
.map(|s| s.as_ref() as &(dyn StdError + 'static)),
Error::Write { source, .. } => source
.as_ref()
.map(|s| s.as_ref() as &(dyn StdError + 'static)),
Error::NotImplemented { .. } => None,
}
}
}
pub type Result<T> = StdResult<T, Error>;
pub trait Converter<T, E> {
fn read_err<C>(self, context: C) -> Result<T>
where
C: Display + Send + Sync + 'static;
fn invalid_err<C>(self, context: C) -> Result<T>
where
C: Display + Send + Sync + 'static;
fn internal_err<C>(self, context: C) -> Result<T>
where
C: Display + Send + Sync + 'static;
fn write_err<C>(self, context: C) -> Result<T>
where
C: Display + Send + Sync + 'static;
}
impl<T, E> Converter<T, E> for StdResult<T, E>
where
E: StdError + Send + Sync + 'static,
{
fn read_err<C>(self, desc: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
match self {
Ok(ok) => Ok(ok),
Err(error) => Err(Error::Read {
desc: desc.to_string(),
source: Some(Box::new(error)),
}),
}
}
fn invalid_err<C>(self, desc: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
match self {
Ok(ok) => Ok(ok),
Err(error) => Err(Error::Invalid {
desc: desc.to_string(),
source: Some(Box::new(error)),
}),
}
}
fn internal_err<C>(self, desc: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
match self {
Ok(ok) => Ok(ok),
Err(error) => Err(Error::Internal {
desc: desc.to_string(),
source: Some(Box::new(error)),
}),
}
}
fn write_err<C>(self, desc: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
match self {
Ok(ok) => Ok(ok),
Err(error) => Err(Error::Write {
desc: desc.to_string(),
source: Some(Box::new(error)),
}),
}
}
}
impl<T> Converter<T, Infallible> for Option<T> {
fn read_err<C>(self, desc: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
match self {
Some(ok) => Ok(ok),
None => Err(Error::Read {
desc: desc.to_string(),
source: None,
}),
}
}
fn invalid_err<C>(self, desc: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
match self {
Some(ok) => Ok(ok),
None => Err(Error::Invalid {
desc: desc.to_string(),
source: None,
}),
}
}
fn internal_err<C>(self, desc: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
match self {
Some(ok) => Ok(ok),
None => Err(Error::Internal {
desc: desc.to_string(),
source: None,
}),
}
}
fn write_err<C>(self, desc: C) -> Result<T>
where
C: Display + Send + Sync + 'static,
{
match self {
Some(ok) => Ok(ok),
None => Err(Error::Write {
desc: desc.to_string(),
source: None,
}),
}
}
}