1use std::fmt;
7
8#[derive(Debug)]
10pub enum Error {
11 AuthFailed,
13 Serialize(sonic_rs::Error),
15 UnknownCommand(String),
17 DecodeFailed,
19 PayloadTooLarge(usize),
21 ChannelFull,
24 Handler(String),
26 UnknownChannel(String),
28}
29
30impl fmt::Display for Error {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 match self {
33 Self::AuthFailed => f.write_str("authentication failed"),
34 Self::Serialize(e) => write!(f, "serialization error: {e}"),
35 Self::UnknownCommand(name) => write!(f, "unknown command: {name}"),
36 Self::DecodeFailed => f.write_str("binary decode failed"),
37 Self::PayloadTooLarge(len) => {
38 write!(f, "payload too large: {len} bytes exceeds u32::MAX")
39 }
40 Self::ChannelFull => f.write_str("channel full: byte limit reached"),
41 Self::Handler(msg) => write!(f, "handler error: {msg}"),
42 Self::UnknownChannel(name) => write!(f, "unknown channel: {name}"),
43 }
44 }
45}
46
47impl std::error::Error for Error {
48 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
49 match self {
50 Self::Serialize(e) => Some(e),
51 _ => None,
52 }
53 }
54}
55
56impl From<sonic_rs::Error> for Error {
57 fn from(e: sonic_rs::Error) -> Self {
58 Self::Serialize(e)
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn display_auth_failed() {
68 let err = Error::AuthFailed;
69 assert_eq!(err.to_string(), "authentication failed");
70 }
71
72 #[test]
73 fn display_unknown_command() {
74 let err = Error::UnknownCommand("foo".into());
75 assert_eq!(err.to_string(), "unknown command: foo");
76 }
77
78 #[test]
79 fn from_sonic_rs() {
80 let json_err = sonic_rs::from_str::<String>("not json").unwrap_err();
81 let err: Error = json_err.into();
82 assert!(matches!(err, Error::Serialize(_)));
83 }
84
85 #[test]
86 fn error_source_none_variants() {
87 assert!(std::error::Error::source(&Error::AuthFailed).is_none());
88 assert!(std::error::Error::source(&Error::DecodeFailed).is_none());
89 assert!(std::error::Error::source(&Error::PayloadTooLarge(0)).is_none());
90 }
91
92 #[test]
93 fn display_payload_too_large() {
94 let err = Error::PayloadTooLarge(5_000_000_000);
95 assert_eq!(
96 err.to_string(),
97 "payload too large: 5000000000 bytes exceeds u32::MAX"
98 );
99 }
100
101 #[test]
102 fn display_decode_failed() {
103 let err = Error::DecodeFailed;
104 assert_eq!(err.to_string(), "binary decode failed");
105 }
106
107 #[test]
108 fn display_channel_full() {
109 let err = Error::ChannelFull;
110 assert_eq!(err.to_string(), "channel full: byte limit reached");
111 }
112
113 #[test]
114 fn error_source_channel_full() {
115 assert!(std::error::Error::source(&Error::ChannelFull).is_none());
116 }
117
118 #[test]
119 fn display_handler_error() {
120 let err = Error::Handler("division by zero".into());
121 assert_eq!(err.to_string(), "handler error: division by zero");
122 }
123
124 #[test]
125 fn error_source_handler() {
126 assert!(std::error::Error::source(&Error::Handler("x".into())).is_none());
127 }
128
129 #[test]
130 fn display_unknown_channel() {
131 let err = Error::UnknownChannel("telemetry".into());
132 assert_eq!(err.to_string(), "unknown channel: telemetry");
133 }
134
135 #[test]
136 fn error_source_unknown_channel() {
137 assert!(std::error::Error::source(&Error::UnknownChannel("x".into())).is_none());
138 }
139}