asteroid-mq 0.1.0-alpha.16

An embeddable message queue system
Documentation
use std::{
    borrow::Cow,
    fmt::{Display, Formatter},
};

use crate::{
    prelude::NodeId,
    protocol::{
        node::durable_message::DurableError,
        node::raft::{raft_node::TcpNode, state_machine::topic::wait_ack::WaitAckError},
    },
};

#[derive(Debug)]
pub struct Error {
    pub context: Cow<'static, str>,
    pub kind: ErrorKind,
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}: {:?}", self.context, self.kind)
    }
}

impl std::error::Error for Error {}

impl Error {
    pub const fn contextual<T: Into<ErrorKind>>(
        context: impl Into<Cow<'static, str>>,
    ) -> impl FnOnce(T) -> Self {
        move |kind| Self {
            context: context.into(),
            kind: kind.into(),
        }
    }
    pub fn new(context: impl Into<Cow<'static, str>>, kind: impl Into<ErrorKind>) -> Self {
        Self {
            context: context.into(),
            kind: kind.into(),
        }
    }
    pub fn unknown(context: impl Into<Cow<'static, str>>) -> Self {
        Self {
            context: context.into(),
            kind: ErrorKind::Custom("unknown error".into()),
        }
    }
    pub fn custom(
        context: impl Into<Cow<'static, str>>,
        error: impl Into<Box<dyn std::error::Error + Send + Sync>>,
    ) -> Self {
        Self {
            context: context.into(),
            kind: ErrorKind::Custom(error.into()),
        }
    }
    pub fn contextual_custom<E: std::error::Error + Send + Sync + 'static>(
        context: impl Into<Cow<'static, str>>,
    ) -> impl FnOnce(E) -> Self {
        move |error| Self {
            context: context.into(),
            kind: ErrorKind::Custom(Box::new(error)),
        }
    }
}

macro_rules! error_kind {
    (
        pub enum $ErrorKind: ident {
            $($Kind: ident$(: $InnerType: ty)?),*
        }
    ) => {
        #[derive(Debug)]
        pub enum ErrorKind {
            $($Kind$(($InnerType))?,)*
        }
        $(
            $(
                impl From<$InnerType> for ErrorKind {
                    fn from(e: $InnerType) -> Self {
                        ErrorKind::$Kind(e)
                    }
                }
            )?
        )*
    };
}
error_kind! {
    pub enum ErrorKind {
        Durability: DurableError,
        Offline,
        TopicAlreadyExists,
        NotLeader,
        Io: std::io::Error,
        Ack: WaitAckError,
        Custom: Box<dyn std::error::Error + Send + Sync>,
        RaftClient: openraft::error::RaftError<NodeId, openraft::error::ClientWriteError<NodeId, TcpNode>>,
        Raft: openraft::error::RaftError<NodeId>
    }
}