1use core::fmt;
2
3use rdkafka::error::KafkaError;
4
5#[derive(Debug)]
6pub enum Error {
7 Custom(CustomError),
8 Kafka(KafkaError),
9 TokioIo(tokio::io::Error),
10}
11
12#[derive(Debug)]
13pub enum ErrorKind {
14 Simple(String),
15 NoStdout,
16}
17
18#[derive(Debug)]
19pub struct CustomError {
20 kind: ErrorKind,
21 reason: Option<Box<dyn std::error::Error + Send + Sync>>,
22}
23
24impl Error {
25 pub fn new(reason: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> Self {
26 let reason = reason.into();
27 Self::Custom(CustomError {
28 kind: ErrorKind::Simple(reason.to_string()),
29 reason: Some(reason),
30 })
31 }
32
33 pub fn kafka(err: KafkaError) -> Self {
34 Self::Kafka(err)
35 }
36
37 pub fn no_stdout() -> Self {
38 Self::Custom(CustomError {
39 kind: ErrorKind::NoStdout,
40 reason: None,
41 })
42 }
43
44 pub fn tokio_io(err: tokio::io::Error) -> Self {
45 Self::TokioIo(err)
46 }
47}
48
49impl fmt::Display for Error {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 match self {
52 Self::Custom(custom) => match &custom.reason {
53 Some(reason) => write!(f, "kind: {:?}, reason: {}", custom.kind, reason),
54 None => write!(f, "kind: {:?}", custom.kind),
55 },
56 Self::Kafka(err) => write!(f, "kafka error: {}", err),
57 Self::TokioIo(err) => write!(f, "tokio io error: {}", err),
58 }
59 }
60}
61
62impl std::error::Error for Error {
63 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
64 match self {
65 Error::Custom(custom) => custom
66 .reason
67 .as_deref()
68 .map(|err| err as &dyn std::error::Error),
69 _ => None,
70 }
71 }
72}
73
74impl From<KafkaError> for Error {
75 fn from(err: KafkaError) -> Self {
76 Self::kafka(err)
77 }
78}
79
80impl From<tokio::io::Error> for Error {
81 fn from(err: tokio::io::Error) -> Self {
82 Self::tokio_io(err)
83 }
84}