Skip to main content

iperf3_rs/
error.rs

1//! Error types returned by the public library API.
2
3use std::error::Error as StdError;
4use std::fmt;
5
6/// Result type used by the public iperf3-rs library API.
7pub type Result<T> = std::result::Result<T, Error>;
8
9/// Broad category for an [`Error`].
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11#[non_exhaustive]
12pub enum ErrorKind {
13    /// The supplied iperf or iperf3-rs argument was invalid.
14    InvalidArgument,
15    /// The requested metrics mode is not valid.
16    InvalidMetricsMode,
17    /// Upstream libiperf reported an error.
18    Libiperf,
19    /// Pushgateway configuration or delivery failed.
20    PushGateway,
21    /// Writing metrics file output failed.
22    MetricsFile,
23    /// The background iperf worker failed before producing a normal result.
24    Worker,
25    /// An internal synchronization or setup invariant failed.
26    Internal,
27}
28
29/// Error returned by the public library API.
30#[derive(Debug)]
31pub struct Error {
32    kind: ErrorKind,
33    message: String,
34    source: Option<Box<dyn StdError + Send + Sync + 'static>>,
35}
36
37impl Error {
38    /// Create an error with a category and message.
39    pub fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
40        Self {
41            kind,
42            message: message.into(),
43            source: None,
44        }
45    }
46
47    /// Return the broad error category.
48    pub fn kind(&self) -> ErrorKind {
49        self.kind
50    }
51
52    /// Return the human-readable error message.
53    pub fn message(&self) -> &str {
54        &self.message
55    }
56
57    pub(crate) fn invalid_argument(message: impl Into<String>) -> Self {
58        Self::new(ErrorKind::InvalidArgument, message)
59    }
60
61    pub(crate) fn invalid_metrics_mode(message: impl Into<String>) -> Self {
62        Self::new(ErrorKind::InvalidMetricsMode, message)
63    }
64
65    pub(crate) fn libiperf(message: impl Into<String>) -> Self {
66        Self::new(ErrorKind::Libiperf, message)
67    }
68
69    #[cfg(feature = "pushgateway")]
70    pub(crate) fn pushgateway(message: impl Into<String>) -> Self {
71        Self::new(ErrorKind::PushGateway, message)
72    }
73
74    pub(crate) fn worker(message: impl Into<String>) -> Self {
75        Self::new(ErrorKind::Worker, message)
76    }
77
78    pub(crate) fn internal(message: impl Into<String>) -> Self {
79        Self::new(ErrorKind::Internal, message)
80    }
81
82    #[cfg(any(feature = "pushgateway", feature = "serde"))]
83    pub(crate) fn with_source(
84        kind: ErrorKind,
85        message: impl Into<String>,
86        source: impl StdError + Send + Sync + 'static,
87    ) -> Self {
88        Self {
89            kind,
90            message: message.into(),
91            source: Some(Box::new(source)),
92        }
93    }
94}
95
96impl fmt::Display for Error {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        f.write_str(&self.message)
99    }
100}
101
102impl StdError for Error {
103    fn source(&self) -> Option<&(dyn StdError + 'static)> {
104        self.source
105            .as_deref()
106            .map(|source| source as &(dyn StdError + 'static))
107    }
108}