Error refactor for peach-lib #38
|
@ -1,136 +1,222 @@
|
|||
//! Basic error handling for the network, OLED, stats and dyndns JSON-RPC clients.
|
||||
pub use snafu::ResultExt;
|
||||
use snafu::Snafu;
|
||||
use std::error;
|
||||
pub type BoxError = Box<dyn error::Error>;
|
||||
#![warn(missing_docs)]
|
||||
|
||||
#[derive(Debug, Snafu)]
|
||||
#[snafu(visibility(pub(crate)))]
|
||||
//! Error handling for various aspects of the PeachCloud system, including the network, OLED, stats and dyndns JSON-RPC clients, as well as the configuration manager, sbot client and password utilities.
|
||||
|
||||
use std::{io, str, string};
|
||||
|
||||
/// This type represents all possible errors that can occur when interacting with the PeachCloud library.
|
||||
#[derive(Debug)]
|
||||
pub enum PeachError {
|
||||
#[snafu(display("{}", source))]
|
||||
JsonRpcHttp { source: jsonrpc_client_http::Error },
|
||||
#[snafu(display("{}", source))]
|
||||
JsonRpcClientCore { source: jsonrpc_client_core::Error },
|
||||
#[snafu(display("{}", source))]
|
||||
Serde { source: serde_json::error::Error },
|
||||
#[snafu(display("{}", source))]
|
||||
PeachParseBoolError { source: std::str::ParseBoolError },
|
||||
#[snafu(display("{}", source))]
|
||||
SetConfigError { source: serde_yaml::Error },
|
||||
#[snafu(display("Failed to read: {}", file))]
|
||||
ReadConfigError {
|
||||
source: std::io::Error,
|
||||
file: String,
|
||||
},
|
||||
#[snafu(display("Failed to save: {}", file))]
|
||||
WriteConfigError {
|
||||
source: std::io::Error,
|
||||
file: String,
|
||||
},
|
||||
#[snafu(display("Failed to save tsig key: {} {}", path, source))]
|
||||
SaveTsigKeyError {
|
||||
source: std::io::Error,
|
||||
path: String,
|
||||
},
|
||||
#[snafu(display("{}", msg))]
|
||||
NsUpdateError { msg: String },
|
||||
#[snafu(display("Failed to run nsupdate: {}", source))]
|
||||
NsCommandError { source: std::io::Error },
|
||||
#[snafu(display("Failed to get public IP address: {}", source))]
|
||||
GetPublicIpError { source: std::io::Error },
|
||||
#[snafu(display("Failed to decode public ip: {}", source))]
|
||||
DecodePublicIpError { source: std::str::Utf8Error },
|
||||
#[snafu(display("Failed to decode nsupdate output: {}", source))]
|
||||
DecodeNsUpdateOutputError { source: std::string::FromUtf8Error },
|
||||
#[snafu(display("{}", source))]
|
||||
YamlError { source: serde_yaml::Error },
|
||||
#[snafu(display("{:?}", err))]
|
||||
JsonRpcCore { err: jsonrpc_core::Error },
|
||||
#[snafu(display("Error creating regex: {}", source))]
|
||||
RegexError { source: regex::Error },
|
||||
#[snafu(display("Failed to decode utf8: {}", source))]
|
||||
FromUtf8Error { source: std::string::FromUtf8Error },
|
||||
#[snafu(display("Encountered Utf8Error: {}", source))]
|
||||
Utf8Error { source: std::str::Utf8Error },
|
||||
#[snafu(display("Stdio error: {}: {}", msg, source))]
|
||||
StdIoError { source: std::io::Error, msg: String },
|
||||
#[snafu(display("Failed to parse time from {} {}", source, msg))]
|
||||
ChronoParseError {
|
||||
source: chrono::ParseError,
|
||||
/// Represents all other cases of `std::io::Error`.
|
||||
Io(io::Error),
|
||||
|
||||
/// Represents a JSON-RPC core error returned from a JSON-RPC client.
|
||||
JsonRpcClientCore(jsonrpc_client_core::Error),
|
||||
|
||||
/// Represents a JSON-RPC core error returned from a JSON-RPC server.
|
||||
JsonRpcCore(jsonrpc_core::Error),
|
||||
|
||||
/// Represents a JSON-RPC HTTP error returned from a JSON-RPC client.
|
||||
JsonRpcHttp(jsonrpc_client_http::Error),
|
||||
|
||||
/// Represents a failure to update the nameserver.
|
||||
NsUpdate {
|
||||
/// A message describing the context of the attempted nameserver update.
|
||||
msg: String,
|
||||
},
|
||||
#[snafu(display("Failed to save dynamic dns success log: {}", source))]
|
||||
SaveDynDnsResultError { source: std::io::Error },
|
||||
#[snafu(display("New passwords do not match"))]
|
||||
PasswordsDoNotMatch,
|
||||
#[snafu(display("No admin password is set"))]
|
||||
|
||||
/// Represents a failure to parse a string slice to a boolean value.
|
||||
ParseBool(str::ParseBoolError),
|
||||
|
||||
/// Represents a failure to parse a `DateTime`. Includes the error source and the file path
|
||||
/// used in the parse attempt.
|
||||
ParseDateTime {
|
||||
/// The underlying source of the error.
|
||||
source: chrono::ParseError,
|
||||
/// The file path for the parse attempt.
|
||||
path: String,
|
||||
},
|
||||
|
||||
/// Represents the submission of an incorrect admin password.
|
||||
PasswordIncorrect,
|
||||
|
||||
/// Represents the submission of two passwords which do not match.
|
||||
PasswordMismatch,
|
||||
|
||||
/// Represents an unset admin password (empty password hash value) in the config file.
|
||||
PasswordNotSet,
|
||||
#[snafu(display("The supplied password was not correct"))]
|
||||
InvalidPassword,
|
||||
#[snafu(display("Error saving new password: {}", msg))]
|
||||
FailedToSetNewPassword { msg: String },
|
||||
#[snafu(display("Error calling sbotcli: {}", msg))]
|
||||
SbotCliError { msg: String },
|
||||
#[snafu(display("Error deleting ssb admin id, id not found"))]
|
||||
SsbAdminIdNotFound { id: String },
|
||||
|
||||
/// Represents a failure to read from input. Includes the error source and the file path used
|
||||
/// in the read attempt.
|
||||
Read {
|
||||
/// The underlying source of the error.
|
||||
source: io::Error,
|
||||
/// The file path for the read attempt.
|
||||
path: String,
|
||||
},
|
||||
|
||||
/// Represents a failure to parse or compile a regular expression.
|
||||
Regex(regex::Error),
|
||||
|
||||
/// Represents a failure to successfully execute an sbot command.
|
||||
SbotCli {
|
||||
/// The `stderr` output from the sbot command.
|
||||
msg: String,
|
||||
},
|
||||
|
||||
/// Represents a failure to serialize or deserialize JSON.
|
||||
SerdeJson(serde_json::error::Error),
|
||||
|
||||
/// Represents a failure to serialize or deserialize YAML.
|
||||
SerdeYaml(serde_yaml::Error),
|
||||
|
||||
/// Represents a failure to find the given SSB ID in the config file.
|
||||
SsbAdminIdNotFound {
|
||||
/// An SSB ID (public key).
|
||||
id: String,
|
||||
},
|
||||
|
||||
/// Represents a failure to interpret a sequence of u8 as a string slice.
|
||||
Utf8ToStr(str::Utf8Error),
|
||||
|
||||
/// Represents a failure to interpret a sequence of u8 as a String.
|
||||
Utf8ToString(string::FromUtf8Error),
|
||||
|
||||
/// Represents a failure to write to output. Includes the error source and the file path used
|
||||
/// in the write attempt.
|
||||
Write {
|
||||
/// The underlying source of the error.
|
||||
source: io::Error,
|
||||
/// The file path for the write attemp.
|
||||
path: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<jsonrpc_client_http::Error> for PeachError {
|
||||
fn from(err: jsonrpc_client_http::Error) -> PeachError {
|
||||
PeachError::JsonRpcHttp { source: err }
|
||||
impl std::error::Error for PeachError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match *self {
|
||||
PeachError::Io(_) => None,
|
||||
PeachError::JsonRpcClientCore(_) => None,
|
||||
PeachError::JsonRpcCore(_) => None,
|
||||
PeachError::JsonRpcHttp(_) => None,
|
||||
PeachError::NsUpdate { .. } => None,
|
||||
PeachError::ParseBool(_) => None,
|
||||
PeachError::ParseDateTime { ref source, .. } => Some(source),
|
||||
PeachError::PasswordIncorrect => None,
|
||||
PeachError::PasswordMismatch => None,
|
||||
PeachError::PasswordNotSet => None,
|
||||
PeachError::Read { ref source, .. } => Some(source),
|
||||
PeachError::Regex(_) => None,
|
||||
PeachError::SbotCli { .. } => None,
|
||||
PeachError::SerdeJson(_) => None,
|
||||
PeachError::SerdeYaml(_) => None,
|
||||
PeachError::SsbAdminIdNotFound { .. } => None,
|
||||
PeachError::Utf8ToStr(_) => None,
|
||||
PeachError::Utf8ToString(_) => None,
|
||||
PeachError::Write { ref source, .. } => Some(source),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<jsonrpc_client_core::Error> for PeachError {
|
||||
fn from(err: jsonrpc_client_core::Error) -> PeachError {
|
||||
PeachError::JsonRpcClientCore { source: err }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::error::Error> for PeachError {
|
||||
fn from(err: serde_json::error::Error) -> PeachError {
|
||||
PeachError::Serde { source: err }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_yaml::Error> for PeachError {
|
||||
fn from(err: serde_yaml::Error) -> PeachError {
|
||||
PeachError::YamlError { source: err }
|
||||
impl std::fmt::Display for PeachError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match *self {
|
||||
PeachError::Io(ref err) => err.fmt(f),
|
||||
PeachError::JsonRpcClientCore(ref err) => err.fmt(f),
|
||||
PeachError::JsonRpcCore(ref err) => {
|
||||
write!(f, "{:?}", err)
|
||||
}
|
||||
PeachError::JsonRpcHttp(ref err) => err.fmt(f),
|
||||
PeachError::NsUpdate { ref msg } => {
|
||||
write!(f, "Nameserver error: {}", msg)
|
||||
}
|
||||
PeachError::ParseBool(ref err) => err.fmt(f),
|
||||
PeachError::ParseDateTime { ref path, .. } => {
|
||||
write!(f, "Date/time parse error: {}", path)
|
||||
}
|
||||
PeachError::PasswordIncorrect => {
|
||||
write!(f, "Password error: user-supplied password is incorrect")
|
||||
}
|
||||
PeachError::PasswordMismatch => {
|
||||
write!(f, "Password error: user-supplied passwords do not match")
|
||||
}
|
||||
PeachError::PasswordNotSet => {
|
||||
write!(
|
||||
f,
|
||||
"Password error: hash value in YAML configuration file is empty"
|
||||
)
|
||||
}
|
||||
PeachError::Read { ref path, .. } => {
|
||||
write!(f, "Read error: {}", path)
|
||||
}
|
||||
PeachError::Regex(ref err) => err.fmt(f),
|
||||
PeachError::SbotCli { ref msg } => {
|
||||
write!(f, "Sbot error: {}", msg)
|
||||
}
|
||||
PeachError::SerdeJson(ref err) => err.fmt(f),
|
||||
PeachError::SerdeYaml(ref err) => err.fmt(f),
|
||||
PeachError::SsbAdminIdNotFound { ref id } => {
|
||||
write!(f, "Config error: SSB admin ID `{}` not found", id)
|
||||
}
|
||||
PeachError::Utf8ToStr(ref err) => err.fmt(f),
|
||||
PeachError::Utf8ToString(ref err) => err.fmt(f),
|
||||
PeachError::Write { ref path, .. } => {
|
||||
write!(f, "Write error: {}", path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for PeachError {
|
||||
fn from(err: std::io::Error) -> PeachError {
|
||||
PeachError::StdIoError {
|
||||
source: err,
|
||||
msg: "".to_string(),
|
||||
}
|
||||
PeachError::Io(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<jsonrpc_client_core::Error> for PeachError {
|
||||
fn from(err: jsonrpc_client_core::Error) -> PeachError {
|
||||
PeachError::JsonRpcClientCore(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<jsonrpc_client_http::Error> for PeachError {
|
||||
fn from(err: jsonrpc_client_http::Error) -> PeachError {
|
||||
PeachError::JsonRpcHttp(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<str::ParseBoolError> for PeachError {
|
||||
fn from(err: str::ParseBoolError) -> PeachError {
|
||||
PeachError::ParseBool(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<regex::Error> for PeachError {
|
||||
fn from(err: regex::Error) -> PeachError {
|
||||
PeachError::RegexError { source: err }
|
||||
PeachError::Regex(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::string::FromUtf8Error> for PeachError {
|
||||
fn from(err: std::string::FromUtf8Error) -> PeachError {
|
||||
PeachError::FromUtf8Error { source: err }
|
||||
impl From<serde_json::error::Error> for PeachError {
|
||||
fn from(err: serde_json::error::Error) -> PeachError {
|
||||
PeachError::SerdeJson(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::str::Utf8Error> for PeachError {
|
||||
fn from(err: std::str::Utf8Error) -> PeachError {
|
||||
PeachError::Utf8Error { source: err }
|
||||
impl From<serde_yaml::Error> for PeachError {
|
||||
fn from(err: serde_yaml::Error) -> PeachError {
|
||||
PeachError::SerdeYaml(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<chrono::ParseError> for PeachError {
|
||||
fn from(err: chrono::ParseError) -> PeachError {
|
||||
PeachError::ChronoParseError {
|
||||
source: err,
|
||||
msg: "".to_string(),
|
||||
}
|
||||
impl From<str::Utf8Error> for PeachError {
|
||||
fn from(err: str::Utf8Error) -> PeachError {
|
||||
PeachError::Utf8ToStr(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<string::FromUtf8Error> for PeachError {
|
||||
fn from(err: string::FromUtf8Error) -> PeachError {
|
||||
PeachError::Utf8ToString(err)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue