implement custom error type
This commit is contained in:
parent
f17ae95b21
commit
b2f7747357
|
@ -1,136 +1,222 @@
|
||||||
//! Basic error handling for the network, OLED, stats and dyndns JSON-RPC clients.
|
#![warn(missing_docs)]
|
||||||
pub use snafu::ResultExt;
|
|
||||||
use snafu::Snafu;
|
|
||||||
use std::error;
|
|
||||||
pub type BoxError = Box<dyn error::Error>;
|
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
//! 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.
|
||||||
#[snafu(visibility(pub(crate)))]
|
|
||||||
|
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 {
|
pub enum PeachError {
|
||||||
#[snafu(display("{}", source))]
|
/// Represents all other cases of `std::io::Error`.
|
||||||
JsonRpcHttp { source: jsonrpc_client_http::Error },
|
Io(io::Error),
|
||||||
#[snafu(display("{}", source))]
|
|
||||||
JsonRpcClientCore { source: jsonrpc_client_core::Error },
|
/// Represents a JSON-RPC core error returned from a JSON-RPC client.
|
||||||
#[snafu(display("{}", source))]
|
JsonRpcClientCore(jsonrpc_client_core::Error),
|
||||||
Serde { source: serde_json::error::Error },
|
|
||||||
#[snafu(display("{}", source))]
|
/// Represents a JSON-RPC core error returned from a JSON-RPC server.
|
||||||
PeachParseBoolError { source: std::str::ParseBoolError },
|
JsonRpcCore(jsonrpc_core::Error),
|
||||||
#[snafu(display("{}", source))]
|
|
||||||
SetConfigError { source: serde_yaml::Error },
|
/// Represents a JSON-RPC HTTP error returned from a JSON-RPC client.
|
||||||
#[snafu(display("Failed to read: {}", file))]
|
JsonRpcHttp(jsonrpc_client_http::Error),
|
||||||
ReadConfigError {
|
|
||||||
source: std::io::Error,
|
/// Represents a failure to update the nameserver.
|
||||||
file: String,
|
NsUpdate {
|
||||||
},
|
/// A message describing the context of the attempted nameserver update.
|
||||||
#[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,
|
|
||||||
msg: String,
|
msg: String,
|
||||||
},
|
},
|
||||||
#[snafu(display("Failed to save dynamic dns success log: {}", source))]
|
|
||||||
SaveDynDnsResultError { source: std::io::Error },
|
/// Represents a failure to parse a string slice to a boolean value.
|
||||||
#[snafu(display("New passwords do not match"))]
|
ParseBool(str::ParseBoolError),
|
||||||
PasswordsDoNotMatch,
|
|
||||||
#[snafu(display("No admin password is set"))]
|
/// 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,
|
PasswordNotSet,
|
||||||
#[snafu(display("The supplied password was not correct"))]
|
|
||||||
InvalidPassword,
|
/// Represents a failure to read from input. Includes the error source and the file path used
|
||||||
#[snafu(display("Error saving new password: {}", msg))]
|
/// in the read attempt.
|
||||||
FailedToSetNewPassword { msg: String },
|
Read {
|
||||||
#[snafu(display("Error calling sbotcli: {}", msg))]
|
/// The underlying source of the error.
|
||||||
SbotCliError { msg: String },
|
source: io::Error,
|
||||||
#[snafu(display("Error deleting ssb admin id, id not found"))]
|
/// The file path for the read attempt.
|
||||||
SsbAdminIdNotFound { id: String },
|
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 {
|
impl std::error::Error for PeachError {
|
||||||
fn from(err: jsonrpc_client_http::Error) -> PeachError {
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
PeachError::JsonRpcHttp { source: err }
|
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 {
|
impl std::fmt::Display for PeachError {
|
||||||
fn from(err: jsonrpc_client_core::Error) -> PeachError {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
PeachError::JsonRpcClientCore { source: err }
|
match *self {
|
||||||
}
|
PeachError::Io(ref err) => err.fmt(f),
|
||||||
}
|
PeachError::JsonRpcClientCore(ref err) => err.fmt(f),
|
||||||
|
PeachError::JsonRpcCore(ref err) => {
|
||||||
impl From<serde_json::error::Error> for PeachError {
|
write!(f, "{:?}", err)
|
||||||
fn from(err: serde_json::error::Error) -> PeachError {
|
}
|
||||||
PeachError::Serde { source: err }
|
PeachError::JsonRpcHttp(ref err) => err.fmt(f),
|
||||||
}
|
PeachError::NsUpdate { ref msg } => {
|
||||||
}
|
write!(f, "Nameserver error: {}", msg)
|
||||||
|
}
|
||||||
impl From<serde_yaml::Error> for PeachError {
|
PeachError::ParseBool(ref err) => err.fmt(f),
|
||||||
fn from(err: serde_yaml::Error) -> PeachError {
|
PeachError::ParseDateTime { ref path, .. } => {
|
||||||
PeachError::YamlError { source: err }
|
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 {
|
impl From<std::io::Error> for PeachError {
|
||||||
fn from(err: std::io::Error) -> PeachError {
|
fn from(err: std::io::Error) -> PeachError {
|
||||||
PeachError::StdIoError {
|
PeachError::Io(err)
|
||||||
source: err,
|
}
|
||||||
msg: "".to_string(),
|
}
|
||||||
}
|
|
||||||
|
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 {
|
impl From<regex::Error> for PeachError {
|
||||||
fn from(err: regex::Error) -> PeachError {
|
fn from(err: regex::Error) -> PeachError {
|
||||||
PeachError::RegexError { source: err }
|
PeachError::Regex(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<std::string::FromUtf8Error> for PeachError {
|
impl From<serde_json::error::Error> for PeachError {
|
||||||
fn from(err: std::string::FromUtf8Error) -> PeachError {
|
fn from(err: serde_json::error::Error) -> PeachError {
|
||||||
PeachError::FromUtf8Error { source: err }
|
PeachError::SerdeJson(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<std::str::Utf8Error> for PeachError {
|
impl From<serde_yaml::Error> for PeachError {
|
||||||
fn from(err: std::str::Utf8Error) -> PeachError {
|
fn from(err: serde_yaml::Error) -> PeachError {
|
||||||
PeachError::Utf8Error { source: err }
|
PeachError::SerdeYaml(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<chrono::ParseError> for PeachError {
|
impl From<str::Utf8Error> for PeachError {
|
||||||
fn from(err: chrono::ParseError) -> PeachError {
|
fn from(err: str::Utf8Error) -> PeachError {
|
||||||
PeachError::ChronoParseError {
|
PeachError::Utf8ToStr(err)
|
||||||
source: err,
|
}
|
||||||
msg: "".to_string(),
|
}
|
||||||
}
|
|
||||||
|
impl From<string::FromUtf8Error> for PeachError {
|
||||||
|
fn from(err: string::FromUtf8Error) -> PeachError {
|
||||||
|
PeachError::Utf8ToString(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue