1use thiserror::Error as ThisError;
10
11#[derive(Debug, ThisError)]
13#[non_exhaustive]
14pub enum Error {
15 #[error("invalid .pio.json package: {0}")]
18 Malformed(#[source] serde_json::Error),
19
20 #[error("{0}")]
22 UnsupportedVersion(String),
23
24 #[error("model_kind does not match model.kind")]
26 ModelKindMismatch,
27
28 #[error("{0}")]
30 NoSuchIndex(String),
31
32 #[error("{0}")]
34 Payload(String),
35
36 #[error(transparent)]
38 Core(#[from] powerio::Error),
39
40 #[error(transparent)]
42 Multiconductor(#[from] powerio_dist::Error),
43
44 #[error("serializing .pio.json: {0}")]
46 Serialize(#[source] serde_json::Error),
47}
48
49impl From<serde_json::Error> for Error {
50 fn from(error: serde_json::Error) -> Self {
54 Error::Serialize(error)
55 }
56}
57
58impl Error {
59 #[must_use]
61 pub fn category(&self) -> powerio::ErrorCategory {
62 use powerio::ErrorCategory as C;
63 match self {
64 Error::Core(inner) => inner.category(),
65 Error::Malformed(_) | Error::UnsupportedVersion(_) | Error::Multiconductor(_) => {
66 C::Parse
67 }
68 Error::ModelKindMismatch | Error::NoSuchIndex(_) | Error::Payload(_) => C::Data,
69 Error::Serialize(_) => C::Output,
70 }
71 }
72}
73
74pub type Result<T> = std::result::Result<T, Error>;
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80 use powerio::ErrorCategory::{Data, Parse};
81
82 #[test]
83 fn a_version_rejection_is_not_a_syntax_failure() {
84 let version = Error::UnsupportedVersion("stated 0.2.1".into());
87 assert_eq!(version.category(), Parse);
88 assert!(matches!(version, Error::UnsupportedVersion(_)));
89 assert!(matches!(Error::ModelKindMismatch, Error::ModelKindMismatch));
90 assert_eq!(Error::ModelKindMismatch.category(), Data);
91 }
92
93 #[test]
94 fn a_wrapped_hub_error_keeps_its_own_message() {
95 let wrapped: Error = powerio::Error::MissingField("bus").into();
96 assert_eq!(
97 wrapped.to_string(),
98 powerio::Error::MissingField("bus").to_string()
99 );
100 }
101}