laminar_core/io_uring/
error.rs1use std::io;
4
5#[derive(Debug, thiserror::Error)]
7pub enum IoUringError {
8 #[error("Failed to create io_uring ring: {0}")]
10 RingCreation(#[source] io::Error),
11
12 #[error("Failed to register buffers: {0}")]
14 BufferRegistration(#[source] io::Error),
15
16 #[error("Failed to register file descriptors: {0}")]
18 FdRegistration(#[source] io::Error),
19
20 #[error("Submission queue is full")]
22 SubmissionQueueFull,
23
24 #[error("Buffer pool exhausted")]
26 BufferPoolExhausted,
27
28 #[error("Invalid buffer index: {0}")]
30 InvalidBufferIndex(u16),
31
32 #[error("I/O operation failed: {message} (error: {errno})")]
34 OperationFailed {
35 message: String,
37 errno: i32,
39 },
40
41 #[error("Submission failed: {0}")]
43 SubmissionFailed(#[source] io::Error),
44
45 #[error("Wait for completions failed: {0}")]
47 WaitFailed(#[source] io::Error),
48
49 #[error("Invalid configuration: {0}")]
51 InvalidConfig(String),
52
53 #[error("Feature not supported: {feature} requires Linux {required_version}")]
55 FeatureNotSupported {
56 feature: String,
58 required_version: String,
60 },
61
62 #[error("io_uring is not available on this platform (requires Linux 5.10+)")]
64 NotAvailable,
65
66 #[error("File descriptor not registered: {0}")]
68 FdNotRegistered(i32),
69
70 #[error("Ring already closed")]
72 RingClosed,
73
74 #[error("Pending operation not found: {0}")]
76 PendingNotFound(u64),
77}
78
79impl IoUringError {
80 #[must_use]
82 pub fn from_errno(message: impl Into<String>, errno: i32) -> Self {
83 Self::OperationFailed {
84 message: message.into(),
85 errno,
86 }
87 }
88
89 #[must_use]
91 pub const fn is_fatal(&self) -> bool {
92 matches!(
93 self,
94 Self::RingCreation(_)
95 | Self::BufferRegistration(_)
96 | Self::FdRegistration(_)
97 | Self::RingClosed
98 | Self::NotAvailable
99 )
100 }
101
102 #[must_use]
104 pub const fn is_transient(&self) -> bool {
105 matches!(self, Self::SubmissionQueueFull | Self::BufferPoolExhausted)
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn test_error_display() {
115 let err = IoUringError::BufferPoolExhausted;
116 assert_eq!(err.to_string(), "Buffer pool exhausted");
117
118 let err = IoUringError::from_errno("read failed", -5);
119 assert!(err.to_string().contains("read failed"));
120 assert!(err.to_string().contains("-5"));
121 }
122
123 #[test]
124 fn test_is_fatal() {
125 assert!(IoUringError::NotAvailable.is_fatal());
126 assert!(IoUringError::RingClosed.is_fatal());
127 assert!(!IoUringError::BufferPoolExhausted.is_fatal());
128 assert!(!IoUringError::SubmissionQueueFull.is_fatal());
129 }
130
131 #[test]
132 fn test_is_transient() {
133 assert!(IoUringError::SubmissionQueueFull.is_transient());
134 assert!(IoUringError::BufferPoolExhausted.is_transient());
135 assert!(!IoUringError::NotAvailable.is_transient());
136 assert!(!IoUringError::RingClosed.is_transient());
137 }
138}