Skip to main content

asteroid_mq/
error.rs

1use std::{
2    borrow::Cow,
3    fmt::{Display, Formatter},
4};
5
6use crate::{
7    prelude::NodeId,
8    protocol::{
9        node::durable_message::DurableError,
10        node::raft::{raft_node::TcpNode, state_machine::topic::wait_ack::WaitAckError},
11    },
12};
13
14#[derive(Debug)]
15pub struct Error {
16    pub context: Cow<'static, str>,
17    pub kind: ErrorKind,
18}
19
20impl Display for Error {
21    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
22        write!(f, "{}: {:?}", self.context, self.kind)
23    }
24}
25
26impl std::error::Error for Error {}
27
28impl Error {
29    pub const fn contextual<T: Into<ErrorKind>>(
30        context: impl Into<Cow<'static, str>>,
31    ) -> impl FnOnce(T) -> Self {
32        move |kind| Self {
33            context: context.into(),
34            kind: kind.into(),
35        }
36    }
37    pub fn new(context: impl Into<Cow<'static, str>>, kind: impl Into<ErrorKind>) -> Self {
38        Self {
39            context: context.into(),
40            kind: kind.into(),
41        }
42    }
43    pub fn unknown(context: impl Into<Cow<'static, str>>) -> Self {
44        Self {
45            context: context.into(),
46            kind: ErrorKind::Custom("unknown error".into()),
47        }
48    }
49    pub fn custom(
50        context: impl Into<Cow<'static, str>>,
51        error: impl Into<Box<dyn std::error::Error + Send + Sync>>,
52    ) -> Self {
53        Self {
54            context: context.into(),
55            kind: ErrorKind::Custom(error.into()),
56        }
57    }
58    pub fn contextual_custom<E: std::error::Error + Send + Sync + 'static>(
59        context: impl Into<Cow<'static, str>>,
60    ) -> impl FnOnce(E) -> Self {
61        move |error| Self {
62            context: context.into(),
63            kind: ErrorKind::Custom(Box::new(error)),
64        }
65    }
66}
67
68macro_rules! error_kind {
69    (
70        pub enum $ErrorKind: ident {
71            $($Kind: ident$(: $InnerType: ty)?),*
72        }
73    ) => {
74        #[derive(Debug)]
75        pub enum ErrorKind {
76            $($Kind$(($InnerType))?,)*
77        }
78        $(
79            $(
80                impl From<$InnerType> for ErrorKind {
81                    fn from(e: $InnerType) -> Self {
82                        ErrorKind::$Kind(e)
83                    }
84                }
85            )?
86        )*
87    };
88}
89error_kind! {
90    pub enum ErrorKind {
91        Durability: DurableError,
92        Offline,
93        TopicAlreadyExists,
94        NotLeader,
95        Io: std::io::Error,
96        Ack: WaitAckError,
97        Custom: Box<dyn std::error::Error + Send + Sync>,
98        RaftClient: openraft::error::RaftError<NodeId, openraft::error::ClientWriteError<NodeId, TcpNode>>,
99        Raft: openraft::error::RaftError<NodeId>
100    }
101}