use std::error::Error;
use std::fmt::{self, Debug, Display, Formatter};
#[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Serialize};
use crate::thread::ThreadError;
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub enum Never {}
impl Display for Never {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl Error for Never {}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub enum ImplementationError {
Unreachable,
OptionWithUnexpectedNone,
}
impl Display for ImplementationError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
ImplementationError::Unreachable => {
write!(f, "internal error: entered unreachable code")
}
ImplementationError::OptionWithUnexpectedNone => {
write!(f, "an option contained an unexpected None value")
}
}
}
}
impl Error for ImplementationError {}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub enum MultiIntegrationError<Error> {
ZeroIntegration,
IntegrationError(usize, Error),
}
impl<Error: Display> Display for MultiIntegrationError<Error> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
MultiIntegrationError::ZeroIntegration => write!(f, "no integration steps"),
MultiIntegrationError::IntegrationError(index, error) => {
write!(f, "error during integration step {}: {}", index, error)
}
}
}
}
impl<E: Display + Debug + Error + 'static> Error for MultiIntegrationError<E> {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
MultiIntegrationError::ZeroIntegration => None,
MultiIntegrationError::IntegrationError(_, error) => Some(error),
}
}
}
#[non_exhaustive]
#[derive(Clone, Debug, PartialEq, Copy, Eq)]
pub enum StateInitializationError {
InvalidParameterNormalDistribution(rand_distr::NormalError),
IncompatibleSize,
LatticeInitializationError(LatticeInitializationError),
GaussProjectionError,
}
impl From<rand_distr::NormalError> for StateInitializationError {
fn from(err: rand_distr::NormalError) -> Self {
Self::InvalidParameterNormalDistribution(err)
}
}
impl From<LatticeInitializationError> for StateInitializationError {
fn from(err: LatticeInitializationError) -> Self {
Self::LatticeInitializationError(err)
}
}
impl Display for StateInitializationError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidParameterNormalDistribution(error) => {
write!(f, "normal distribution error: {}", error)
}
Self::IncompatibleSize => write!(f, "size of lattice and data are incompatible"),
Self::LatticeInitializationError(err) => {
write!(f, "lattice Initialization error: {}", err)
}
Self::GaussProjectionError => write!(f, "gauss projection could not finish"),
}
}
}
impl Error for StateInitializationError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::InvalidParameterNormalDistribution(error) => Some(error),
Self::IncompatibleSize => None,
Self::LatticeInitializationError(err) => Some(err),
Self::GaussProjectionError => None,
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum ThreadedStateInitializationError {
ThreadingError(ThreadError),
StateInitializationError(StateInitializationError),
}
impl From<ThreadError> for ThreadedStateInitializationError {
fn from(err: ThreadError) -> Self {
Self::ThreadingError(err)
}
}
impl From<StateInitializationError> for ThreadedStateInitializationError {
fn from(err: StateInitializationError) -> Self {
Self::StateInitializationError(err)
}
}
impl Display for ThreadedStateInitializationError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::ThreadingError(error) => write!(f, "thread error: {}", error),
Self::StateInitializationError(error) => write!(f, "{}", error),
}
}
}
impl Error for ThreadedStateInitializationError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::ThreadingError(error) => Some(error),
Self::StateInitializationError(error) => Some(error),
}
}
}
#[non_exhaustive]
#[derive(Clone, Debug, Eq, PartialEq, Copy, Hash)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub enum LatticeInitializationError {
NonPositiveSize,
DimTooSmall,
ZeroDimension,
}
impl Display for LatticeInitializationError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::NonPositiveSize => write!(
f,
"`size` must be strictly greater than 0 and be a finite number"
),
Self::DimTooSmall => write!(f, "`dim` must be greater or equal to 2"),
Self::ZeroDimension => write!(f, "the dimension parameter `D = 0` is not valid"),
}
}
}
impl Error for LatticeInitializationError {}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct ErrorWithOwnedValue<Error, State> {
error: Error,
owned: State,
}
impl<Error, State> ErrorWithOwnedValue<Error, State> {
getter!(
pub const error() -> Error
);
getter!(
pub const owned() -> State
);
pub const fn new(error: Error, owned: State) -> Self {
Self { error, owned }
}
#[allow(clippy::missing_const_for_fn)] pub fn deconstruct(self) -> (Error, State) {
(self.error, self.owned)
}
#[allow(clippy::missing_const_for_fn)] pub fn error_owned(self) -> Error {
self.error
}
}
impl<Error, State> From<(Error, State)> for ErrorWithOwnedValue<Error, State> {
fn from(data: (Error, State)) -> Self {
Self::new(data.0, data.1)
}
}
impl<Error: Display, State: Display> Display for ErrorWithOwnedValue<Error, State> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "error {} with data {}", self.error, self.owned)
}
}
impl<E: Display + Error + Debug + 'static, State: Display + Debug> Error
for ErrorWithOwnedValue<E, State>
{
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(&self.error)
}
}
impl<State> From<ErrorWithOwnedValue<StateInitializationError, State>>
for StateInitializationError
{
fn from(data: ErrorWithOwnedValue<StateInitializationError, State>) -> Self {
data.error
}
}
impl<Error, Data1, Data2> From<ErrorWithOwnedValue<Error, (Data1, Data2)>>
for ErrorWithOwnedValue<Error, Data1>
{
fn from(data: ErrorWithOwnedValue<Error, (Data1, Data2)>) -> Self {
Self::new(data.error, data.owned.0)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn implementation_error() {
assert_eq!(
ImplementationError::Unreachable.to_string(),
"internal error: entered unreachable code"
);
assert_eq!(
ImplementationError::OptionWithUnexpectedNone.to_string(),
"an option contained an unexpected None value"
);
}
#[test]
fn multi_integration_error() {
let e1 = MultiIntegrationError::<LatticeInitializationError>::ZeroIntegration;
assert_eq!(e1.to_string(), "no integration steps");
let index = 2;
let error = LatticeInitializationError::DimTooSmall;
let e2 = MultiIntegrationError::IntegrationError(index, error);
assert_eq!(
e2.to_string(),
format!("error during integration step {}: {}", index, error)
);
assert!(e1.source().is_none());
assert!(e2.source().is_some());
}
#[allow(clippy::missing_const_for_fn)] #[test]
fn never_size() {
assert_eq!(std::mem::size_of::<Never>(), 0);
}
}