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>;