use std::{error, fmt, result};
use serde_json::json;
use crate::proto::Msg;
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
pub enum ErrorKind {
Config,
Programming,
Parsing,
Protocol,
NoSuchModule,
NoSuchParameter,
NoSuchCommand,
CommandFailed,
CommandRunning,
ReadOnly,
BadValue,
CommunicationFailed,
Timeout, HardwareError, IsBusy,
IsError,
Disabled,
}
#[derive(Debug)]
pub struct Error {
kind: ErrorKind,
message: String,
}
impl Error {
pub fn new(kind: ErrorKind, msg: impl Into<String>) -> Self {
Self { kind, message: msg.into() }
}
pub fn bad_value(msg: impl Into<String>) -> Self {
Self { kind: ErrorKind::BadValue, message: msg.into() }
}
pub fn amend(mut self, msg: &str) -> Self {
self.message = format!("{} ({})", self.message, msg);
self
}
pub fn into_msg(self, msg: String) -> Msg {
Msg::ErrMsg {
class: self.wire().into(),
report: json!([msg, self.message, {}])
}
}
fn wire(&self) -> &str {
use self::ErrorKind::*;
match self.kind {
Config | Programming | Parsing => "InternalError",
Protocol => "ProtocolError",
NoSuchModule => "NoSuchModule",
NoSuchParameter => "NoSuchParameter",
NoSuchCommand => "NoSuchCommand",
CommandFailed => "CommandFailed",
CommandRunning => "CommandRunning",
ReadOnly => "ReadOnly",
BadValue => "BadValue",
CommunicationFailed => "CommunicationFailed",
Timeout => "CommunicationFailed",
HardwareError => "CommunicationFailed",
IsBusy => "IsBusy",
IsError => "IsError",
Disabled => "Disabled",
}
}
pub fn config(msg: impl Into<String>) -> Self {
Self { kind: ErrorKind::Config, message: msg.into() }
}
pub fn protocol(msg: impl Into<String>) -> Self {
Self { kind: ErrorKind::Protocol, message: msg.into() }
}
pub fn no_module() -> Self {
Self { kind: ErrorKind::NoSuchModule, message: "".into() }
}
pub fn no_param() -> Self {
Self { kind: ErrorKind::NoSuchParameter, message: "".into() }
}
pub fn no_command() -> Self {
Self { kind: ErrorKind::NoSuchCommand, message: "".into() }
}
pub fn comm_failed(msg: impl Into<String>) -> Self {
Self { kind: ErrorKind::CommunicationFailed, message: msg.into() }
}
}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
Error::comm_failed(e.to_string())
}
}
impl error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: {}", self.wire(), self.message)
}
}