tosca_controller/
error.rs1use std::borrow::Cow;
2
3use tracing::error;
4
5#[derive(Debug, Copy, Clone, PartialEq)]
7pub enum ErrorKind {
8 Discovery,
10 Request,
12 InvalidParameter,
14 JsonResponse,
16 #[cfg(feature = "stream")]
18 StreamResponse,
19 Sender,
21 Events,
23}
24
25impl ErrorKind {
26 pub(crate) const fn description(self) -> &'static str {
27 match self {
28 Self::Discovery => "Discovery",
29 Self::Request => "Request",
30 Self::InvalidParameter => "Invalid Parameter",
31 Self::JsonResponse => "Json Response",
32 #[cfg(feature = "stream")]
33 Self::StreamResponse => "Stream Response",
34 Self::Sender => "Response Sender",
35 Self::Events => "Events",
36 }
37 }
38}
39
40impl std::fmt::Display for ErrorKind {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 self.description().fmt(f)
43 }
44}
45
46#[derive(PartialEq)]
48pub struct Error {
49 kind: ErrorKind,
50 description: Cow<'static, str>,
51}
52
53impl std::fmt::Display for Error {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 self.format(f)
56 }
57}
58
59impl std::fmt::Debug for Error {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 self.format(f)
62 }
63}
64
65impl Error {
66 #[inline]
68 pub fn new(kind: ErrorKind, description: impl Into<Cow<'static, str>>) -> Self {
69 let description = description.into();
70 error!("{}", description.as_ref());
71 Self { kind, description }
72 }
73
74 fn format(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 write!(f, "{}: {}", self.kind, self.description)
76 }
77}
78
79impl From<reqwest::Error> for Error {
80 fn from(e: reqwest::Error) -> Self {
81 Self::new(ErrorKind::Request, e.to_string())
82 }
83}
84
85impl From<mdns_sd::Error> for Error {
86 fn from(e: mdns_sd::Error) -> Self {
87 Self::new(ErrorKind::Discovery, e.to_string())
88 }
89}
90
91impl From<rumqttc::v5::ClientError> for Error {
92 fn from(e: rumqttc::v5::ClientError) -> Self {
93 Self::new(ErrorKind::Events, e.to_string())
94 }
95}
96
97impl std::error::Error for Error {
98 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
99 Some(self)
100 }
101}
102
103pub type Result<T> = std::result::Result<T, Error>;
105
106#[cfg(test)]
107mod tests {
108 use super::{Error, ErrorKind};
109
110 #[test]
111 fn controller_error() {
112 let error = Error::new(ErrorKind::Discovery, "Process failed.");
113
114 assert_eq!(error.to_string(), r"Discovery: Process failed.");
115 }
116}