use std::fmt;
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
AllProvidersFailed(Vec<ProviderError>),
NoProvidersForVersion,
ConsensusNotReached {
required: usize,
got: usize,
errors: Vec<ProviderError>,
},
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::AllProvidersFailed(errors) => write!(f, "all providers failed: {:?}", errors),
Error::NoProvidersForVersion => {
write!(f, "no providers support the requested IP version")
}
Error::ConsensusNotReached {
required,
got,
errors,
} => {
write!(
f,
"consensus not reached (required {}, got {}, {} provider errors)",
required,
got,
errors.len()
)
}
}
}
}
impl std::error::Error for Error {}
#[derive(Debug)]
pub struct ProviderError {
pub provider: String,
pub error: Box<dyn std::error::Error + Send + Sync>,
}
impl fmt::Display for ProviderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.provider, self.error)
}
}
impl std::error::Error for ProviderError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(self.error.as_ref())
}
}
impl ProviderError {
pub fn new<E>(provider: impl Into<String>, error: E) -> Self
where
E: std::error::Error + Send + Sync + 'static,
{
Self {
provider: provider.into(),
error: Box::new(error),
}
}
pub fn message(provider: impl Into<String>, msg: impl Into<String>) -> Self {
Self {
provider: provider.into(),
error: Box::new(StringError(msg.into())),
}
}
}
#[derive(Debug)]
struct StringError(String);
impl fmt::Display for StringError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl std::error::Error for StringError {}