1#[derive(Debug, Clone)]
2pub struct Error {
3 kind: ErrorKind,
4 description: Option<String>,
5 help: Option<String>,
6}
7
8#[derive(Debug, Clone)]
9pub enum ErrorKind {
10 PermissionDenied,
11 FanControlDisabled,
12 InvalidValue,
13 FileNotFound,
14 ValueTooHigh,
15 ValueTooLow,
16 GenericError,
17}
18
19#[macro_export]
33macro_rules! err {
34 ($kind:expr) => {
35 $crate::error::Error::without_description_help($kind)
36 };
37 ($kind:ident,$description:expr) => {
38 $crate::error::Error::without_help($crate::error::ErrorKind::$kind, $description.to_string())
39 };
40 ($kind:ident,$help: expr, $description: expr) => {
41 $crate::error::Error::new($crate::error::ErrorKind::$kind, $description.to_string(), $help.to_string())
42 };
43 ($kind:ident,$help:expr, $format:expr, $($fmt_arg:tt)*) => {
44 $crate::error::Error::new($crate::error::ErrorKind::$kind, format!($format, $($fmt_arg)*), $help.to_string())
45 };
46 ($kind:ident,$format:expr,$($fmt_arg:tt)*) => {
47 $crate::error::Error::without_help($crate::error::ErrorKind::$kind, format!($format, $($fmt_arg)*))
48 };
49}
50
51#[macro_export]
52macro_rules! generic_err {
54 ($err:expr) => {
55 $crate::err!(GenericError, "Some error occurred: {}", $err)
56 };
57}
58
59pub use crate::{err, generic_err};
60
61impl std::fmt::Display for ErrorKind {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 use ErrorKind as E;
64 let s = match self {
65 E::ValueTooLow => "Fan speed setting too low",
66 E::ValueTooHigh => "Fan speed setting too high",
67 E::InvalidValue => "Fan speed setting invalid",
68 E::FileNotFound => "File not found",
69 E::PermissionDenied => "Permission Denied",
70 E::FanControlDisabled => "Fan control disabled",
71 E::GenericError => "Generic error",
72 };
73
74 write!(f, "{s}")
75 }
76}
77
78impl Error {
79 pub fn new(kind: ErrorKind, description: String, help: String) -> Self {
80 Self {
81 kind,
82 description: Some(description),
83 help: Some(help),
84 }
85 }
86
87 pub fn without_description_help(kind: ErrorKind) -> Self {
88 Self {
89 kind,
90 description: None,
91 help: None,
92 }
93 }
94
95 pub fn without_description(kind: ErrorKind, help: String) -> Self {
96 Self {
97 kind,
98 description: None,
99 help: Some(help),
100 }
101 }
102
103 pub fn without_help(kind: ErrorKind, description: String) -> Self {
104 Self {
105 kind,
106 description: Some(description),
107 help: None,
108 }
109 }
110
111 pub fn kind(&self) -> &ErrorKind {
112 &self.kind
113 }
114
115 pub fn desc(&self) -> Option<&str> {
116 if let Some(ref desc) = self.description {
117 Some(desc.as_str())
118 } else {
119 None
120 }
121 }
122
123 pub fn help(&self) -> Option<&str> {
124 if let Some(ref help) = self.help {
125 Some(help.as_str())
126 } else {
127 None
128 }
129 }
130}
131
132impl std::fmt::Display for Error {
133 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134 write!(f, "{}", self.kind())?;
135 if let Some(ref desc) = self.description {
136 write!(f, ": {}", desc)?;
137 }
138 Ok(())
139 }
140}
141
142impl std::error::Error for Error {
143 fn description(&self) -> &str {
144 match &self.description {
145 Some(s) => s.as_ref(),
146 None => "",
147 }
148 }
149
150 fn cause(&self) -> Option<&dyn std::error::Error> {
151 None
152 }
153
154 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
155 None
156 }
157}