1use std::{error, fmt, result};
26use serde_json::json;
27
28use crate::proto::Msg;
29
30
31pub type Result<T> = result::Result<T, Error>;
32
33#[derive(Debug)]
34pub enum ErrorKind {
35 Config,
37 Programming,
38 Parsing,
39 Protocol,
41 NoSuchModule,
42 NoSuchParameter,
43 NoSuchCommand,
44 CommandFailed,
45 CommandRunning,
46 ReadOnly,
47 BadValue,
48 CommunicationFailed,
49 Timeout, HardwareError, IsBusy,
52 IsError,
53 Disabled,
54}
55
56#[derive(Debug)]
57pub struct Error {
58 kind: ErrorKind,
59 message: String,
60}
61
62impl Error {
63 pub fn new(kind: ErrorKind, msg: impl Into<String>) -> Self {
64 Self { kind, message: msg.into() }
65 }
66
67 pub fn bad_value(msg: impl Into<String>) -> Self {
68 Self { kind: ErrorKind::BadValue, message: msg.into() }
69 }
70
71 pub fn amend(mut self, msg: &str) -> Self {
72 self.message = format!("{} ({})", self.message, msg);
73 self
74 }
75
76 pub fn into_msg(self, msg: String) -> Msg {
77 Msg::ErrMsg {
78 class: self.wire().into(),
79 report: json!([msg, self.message, {}])
80 }
81 }
82
83 fn wire(&self) -> &str {
84 use self::ErrorKind::*;
85 match self.kind {
86 Config | Programming | Parsing => "InternalError",
87 Protocol => "ProtocolError",
88 NoSuchModule => "NoSuchModule",
89 NoSuchParameter => "NoSuchParameter",
90 NoSuchCommand => "NoSuchCommand",
91 CommandFailed => "CommandFailed",
92 CommandRunning => "CommandRunning",
93 ReadOnly => "ReadOnly",
94 BadValue => "BadValue",
95 CommunicationFailed => "CommunicationFailed",
96 Timeout => "CommunicationFailed",
97 HardwareError => "CommunicationFailed",
98 IsBusy => "IsBusy",
99 IsError => "IsError",
100 Disabled => "Disabled",
101 }
102 }
103
104 pub fn config(msg: impl Into<String>) -> Self {
107 Self { kind: ErrorKind::Config, message: msg.into() }
108 }
109
110 pub fn protocol(msg: impl Into<String>) -> Self {
111 Self { kind: ErrorKind::Protocol, message: msg.into() }
112 }
113
114 pub fn no_module() -> Self {
115 Self { kind: ErrorKind::NoSuchModule, message: "".into() }
116 }
117
118 pub fn no_param() -> Self {
119 Self { kind: ErrorKind::NoSuchParameter, message: "".into() }
120 }
121
122 pub fn no_command() -> Self {
123 Self { kind: ErrorKind::NoSuchCommand, message: "".into() }
124 }
125
126 pub fn comm_failed(msg: impl Into<String>) -> Self {
127 Self { kind: ErrorKind::CommunicationFailed, message: msg.into() }
128 }
129}
130
131impl From<std::io::Error> for Error {
134 fn from(e: std::io::Error) -> Self {
135 Error::comm_failed(e.to_string())
136 }
137}
138
139impl error::Error for Error {}
140
141impl fmt::Display for Error {
142 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
143 write!(f, "{}: {}", self.wire(), self.message)
144 }
145}