Skip to main content

ip_discovery/
error.rs

1//! Error types for ip-discovery
2
3use std::fmt;
4
5/// Main error type for IP detection
6#[derive(Debug)]
7#[non_exhaustive]
8pub enum Error {
9    /// All configured providers failed
10    AllProvidersFailed(Vec<ProviderError>),
11
12    /// No providers support the requested IP version
13    NoProvidersForVersion,
14
15    /// Consensus could not be reached
16    ConsensusNotReached {
17        /// Minimum number of providers that needed to agree
18        required: usize,
19        /// Maximum number of providers that agreed on the same IP
20        got: usize,
21        /// Errors from providers that failed during consensus
22        errors: Vec<ProviderError>,
23    },
24}
25
26impl fmt::Display for Error {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        match self {
29            Error::AllProvidersFailed(errors) => write!(f, "all providers failed: {:?}", errors),
30            Error::NoProvidersForVersion => {
31                write!(f, "no providers support the requested IP version")
32            }
33            Error::ConsensusNotReached {
34                required,
35                got,
36                errors,
37            } => {
38                write!(
39                    f,
40                    "consensus not reached (required {}, got {}, {} provider errors)",
41                    required,
42                    got,
43                    errors.len()
44                )
45            }
46        }
47    }
48}
49
50impl std::error::Error for Error {}
51
52/// Error from a specific provider
53#[derive(Debug)]
54pub struct ProviderError {
55    /// Name of the provider that failed
56    pub provider: String,
57    /// The error that occurred
58    pub error: Box<dyn std::error::Error + Send + Sync>,
59}
60
61impl fmt::Display for ProviderError {
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        write!(f, "{}: {}", self.provider, self.error)
64    }
65}
66
67impl std::error::Error for ProviderError {
68    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
69        Some(self.error.as_ref())
70    }
71}
72
73impl ProviderError {
74    /// Create a new provider error from any error type.
75    pub fn new<E>(provider: impl Into<String>, error: E) -> Self
76    where
77        E: std::error::Error + Send + Sync + 'static,
78    {
79        Self {
80            provider: provider.into(),
81            error: Box::new(error),
82        }
83    }
84
85    /// Create a new provider error from a message string.
86    pub fn message(provider: impl Into<String>, msg: impl Into<String>) -> Self {
87        Self {
88            provider: provider.into(),
89            error: Box::new(StringError(msg.into())),
90        }
91    }
92}
93
94#[derive(Debug)]
95struct StringError(String);
96
97impl fmt::Display for StringError {
98    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99        write!(f, "{}", self.0)
100    }
101}
102
103impl std::error::Error for StringError {}