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 #[error("Buffer too small: need {needed} bytes but buffer is {capacity} bytes")]
80 BufferTooSmall {
81 needed: usize,
83 capacity: usize,
85 },
86}
87
88impl IoUringError {
89 #[must_use]
91 pub fn from_errno(message: impl Into<String>, errno: i32) -> Self {
92 Self::OperationFailed {
93 message: message.into(),
94 errno,
95 }
96 }
97
98 #[must_use]
100 pub const fn is_fatal(&self) -> bool {
101 matches!(
102 self,
103 Self::RingCreation(_)
104 | Self::BufferRegistration(_)
105 | Self::FdRegistration(_)
106 | Self::RingClosed
107 | Self::NotAvailable
108 )
109 }
110
111 #[must_use]
113 pub const fn is_transient(&self) -> bool {
114 matches!(self, Self::SubmissionQueueFull | Self::BufferPoolExhausted)
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn test_error_display() {
124 let err = IoUringError::BufferPoolExhausted;
125 assert_eq!(err.to_string(), "Buffer pool exhausted");
126
127 let err = IoUringError::from_errno("read failed", -5);
128 assert!(err.to_string().contains("read failed"));
129 assert!(err.to_string().contains("-5"));
130 }
131
132 #[test]
133 fn test_is_fatal() {
134 assert!(IoUringError::NotAvailable.is_fatal());
135 assert!(IoUringError::RingClosed.is_fatal());
136 assert!(!IoUringError::BufferPoolExhausted.is_fatal());
137 assert!(!IoUringError::SubmissionQueueFull.is_fatal());
138 }
139
140 #[test]
141 fn test_is_transient() {
142 assert!(IoUringError::SubmissionQueueFull.is_transient());
143 assert!(IoUringError::BufferPoolExhausted.is_transient());
144 assert!(!IoUringError::NotAvailable.is_transient());
145 assert!(!IoUringError::RingClosed.is_transient());
146 }
147}