1use powerio_core::DiagnosticInfo;
9use thiserror::Error as ThisError;
10
11use crate::diagnostics::codes;
12
13#[derive(Debug, ThisError)]
15#[non_exhaustive]
16pub enum Error {
17 #[error(transparent)]
19 Transmission(#[from] powerio_tx::Error),
20
21 #[error(transparent)]
23 Io(#[from] std::io::Error),
24}
25
26impl Error {
27 #[must_use]
30 pub fn code(&self) -> &'static DiagnosticInfo {
31 match self {
32 Error::Transmission(inner) => inner.code(),
33 Error::Io(_) => &codes::READ_INSTANCE_IO_FAILED,
34 }
35 }
36
37 #[must_use]
42 pub fn category(&self) -> powerio_tx::ErrorCategory {
43 use powerio_tx::ErrorCategory as C;
44 match self {
45 Error::Transmission(inner) => inner.category(),
46 Error::Io(_) => C::Io,
47 }
48 }
49}
50
51pub type Result<T> = std::result::Result<T, Error>;
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use powerio_tx::ErrorCategory::Parse;
58
59 #[test]
62 fn every_error_code_publishes_the_category_the_variant_reports() {
63 let every: Vec<Error> = vec![
64 powerio_tx::Error::MissingField("gen").into(),
65 std::io::Error::from(std::io::ErrorKind::NotFound).into(),
66 ];
67 for error in &every {
68 assert_eq!(
69 error.code().category,
70 Some(error.category()),
71 "{}",
72 error.code().code
73 );
74 }
75 }
76
77 #[test]
78 fn a_wrapped_hub_error_keeps_its_own_category_and_message() {
79 let wrapped: Error = powerio_tx::Error::MissingField("gen").into();
80 assert_eq!(wrapped.category(), Parse);
81 assert_eq!(
82 wrapped.to_string(),
83 powerio_tx::Error::MissingField("gen").to_string()
84 );
85 }
86}