Skip to main content

proc_connector/
error.rs

1//! Error types for proc-connector operations.
2
3use std::fmt;
4
5/// Errors that can occur during proc connector operations.
6///
7/// # Example: matching on errors
8///
9/// ```
10/// use proc_connector::Error;
11///
12/// fn handle_error(e: Error) -> String {
13///     match &e {
14///         Error::Os(e) => format!("os error: {e}"),
15///         Error::Truncated => "truncated message".into(),
16///         Error::BufferTooSmall { needed } => {
17///             format!("need {needed} bytes")
18///         }
19///         Error::Interrupted => "interrupted, retry".into(),
20///         Error::ConnectionClosed => "connection closed".into(),
21///         Error::Overrun => "events dropped".into(),
22///         Error::WouldBlock => "would block".into(),
23///     }
24/// }
25///
26/// assert_eq!(handle_error(Error::Truncated), "truncated message");
27/// assert_eq!(
28///     handle_error(Error::BufferTooSmall { needed: 4096 }),
29///     "need 4096 bytes"
30/// );
31/// ```
32///
33/// # Example: using the `From<std::io::Error>` impl
34///
35/// ```
36/// use proc_connector::Error;
37///
38/// fn returns_error() -> Result<(), Error> {
39///     // std::io::Error is automatically converted via From
40///     let _file = std::fs::File::open("/nonexistent")?;
41///     Ok(())
42/// }
43///
44/// let err = returns_error().unwrap_err();
45/// assert!(matches!(err, Error::Os(_)));
46/// ```
47#[derive(Debug)]
48pub enum Error {
49    /// System call failed (socket/bind/sendmsg/recvmsg).
50    ///
51    /// Wraps `std::io::Error` for maximum compatibility.
52    Os(std::io::Error),
53
54    /// Received message is shorter than the minimum protocol header size.
55    Truncated,
56
57    /// Provided receive buffer is too small.
58    BufferTooSmall {
59        /// Minimum buffer size required in bytes.
60        needed: usize,
61    },
62
63    /// Receive was interrupted by a signal; the operation should be retried.
64    Interrupted,
65
66    /// The netlink connection was closed (recv returned 0).
67    ConnectionClosed,
68
69    /// Kernel reports message overrun; some events may have been dropped.
70    ///
71    /// The caller should increase buffer size or consume events faster.
72    Overrun,
73
74    /// Non-blocking recv found no data available (EAGAIN / EWOULDBLOCK).
75    ///
76    /// Only returned when the socket is in non-blocking mode. Callers
77    /// should wait for fd readiness (e.g. via poll/AsyncFd) and retry.
78    WouldBlock,
79}
80
81impl fmt::Display for Error {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        match self {
84            Error::Os(e) => write!(f, "system call error: {e}"),
85            Error::Truncated => write!(f, "truncated message"),
86            Error::BufferTooSmall { needed } => {
87                write!(f, "buffer too small, need at least {needed} bytes")
88            }
89            Error::Interrupted => write!(f, "interrupted by signal"),
90            Error::ConnectionClosed => write!(f, "connection closed"),
91            Error::Overrun => write!(f, "message overrun, events may have been dropped"),
92            Error::WouldBlock => write!(f, "operation would block"),
93        }
94    }
95}
96
97impl std::error::Error for Error {
98    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
99        match self {
100            Error::Os(e) => Some(e),
101            _ => None,
102        }
103    }
104}
105
106impl From<std::io::Error> for Error {
107    fn from(e: std::io::Error) -> Self {
108        Error::Os(e)
109    }
110}
111
112/// Convenience alias for `Result<T, Error>`.
113pub type Result<T> = std::result::Result<T, Error>;