safer_ring/operation/submitted.rs
1//! Submitted state implementation for in-flight operations.
2//!
3//! This module contains functionality for operations that have been submitted
4//! to the kernel and are currently in flight.
5
6use std::os::unix::io::RawFd;
7
8use super::core::{BufferType, FdType, Operation};
9use crate::operation::{Completed, OperationType, Submitted};
10
11impl<'ring, 'buf> Operation<'ring, 'buf, Submitted> {
12 /// Get the operation ID.
13 ///
14 /// This ID is used to track the operation in the completion queue
15 /// and match completions to their corresponding operations.
16 #[inline]
17 pub fn id(&self) -> u64 {
18 self.state.id
19 }
20
21 /// Get the file descriptor for this operation.
22 #[inline]
23 pub fn fd(&self) -> RawFd {
24 match &self.fd {
25 FdType::Raw(fd) => *fd,
26 FdType::Registered(reg_fd) => reg_fd.raw_fd(),
27 FdType::Fixed(fixed_file) => fixed_file.raw_fd(),
28 }
29 }
30
31 /// Get the offset for this operation.
32 #[inline]
33 pub fn offset(&self) -> u64 {
34 self.offset
35 }
36
37 /// Get the operation type.
38 #[inline]
39 pub fn op_type(&self) -> OperationType {
40 self.op_type
41 }
42
43 /// Get buffer information for kernel submission.
44 ///
45 /// Returns a tuple of (pointer, length) for the buffer if present.
46 /// This is used internally by the Ring for kernel submission.
47 ///
48 /// # Safety
49 ///
50 /// The returned pointer is only valid while the buffer remains pinned
51 /// and the operation is in flight. The caller must ensure the buffer
52 /// is not moved or dropped until the operation completes.
53 #[allow(dead_code)] // Used by ring submission logic
54 pub(crate) fn buffer_info(&self) -> Option<(*mut u8, usize)> {
55 match &self.buffer {
56 BufferType::None => None,
57 BufferType::Pinned(buf) => {
58 let slice = buf.as_ref();
59 Some((slice.as_ptr() as *mut u8, slice.len()))
60 }
61 BufferType::Registered(_) => {
62 // For registered buffers, we need to get the buffer info from the registry
63 // This will be handled by the ring during submission
64 None
65 }
66 BufferType::Vectored(_) => {
67 // For vectored operations, buffer info is handled differently
68 // This will be handled by the ring during submission
69 None
70 }
71 }
72 }
73
74 /// Get vectored buffer information for kernel submission.
75 ///
76 /// Returns a vector of (pointer, length) tuples for vectored operations.
77 /// This is used internally by the Ring for vectored operation submission.
78 ///
79 /// # Safety
80 ///
81 /// The returned pointers are only valid while the buffers remain pinned
82 /// and the operation is in flight.
83 #[allow(dead_code)] // Used by ring submission logic
84 pub(crate) fn vectored_buffer_info(&self) -> Option<Vec<(*mut u8, usize)>> {
85 match &self.buffer {
86 BufferType::Vectored(buffers) => {
87 let info: Vec<_> = buffers
88 .iter()
89 .map(|buf| {
90 let slice = buf.as_ref();
91 (slice.as_ptr() as *mut u8, slice.len())
92 })
93 .collect();
94 Some(info)
95 }
96 _ => None,
97 }
98 }
99
100 /// Check if this operation uses a registered buffer.
101 #[inline]
102 pub fn uses_registered_buffer(&self) -> bool {
103 matches!(self.buffer, BufferType::Registered(_))
104 }
105
106 /// Check if this operation uses a registered file descriptor.
107 #[inline]
108 pub fn uses_registered_fd(&self) -> bool {
109 matches!(self.fd, FdType::Registered(_))
110 }
111
112 /// Check if this operation uses a fixed file.
113 #[inline]
114 pub fn uses_fixed_file(&self) -> bool {
115 matches!(self.fd, FdType::Fixed(_))
116 }
117
118 /// Check if this operation is vectored.
119 #[inline]
120 pub fn is_vectored(&self) -> bool {
121 matches!(self.buffer, BufferType::Vectored(_))
122 }
123
124 /// Convert this submitted operation to a completed operation.
125 ///
126 /// This is typically called by the Ring when processing completions.
127 /// The state transition is zero-cost at runtime.
128 ///
129 /// # Arguments
130 ///
131 /// * `result` - The result of the completed operation
132 #[allow(dead_code)]
133 pub(crate) fn complete_with_result<T>(self, result: T) -> Operation<'ring, 'buf, Completed<T>> {
134 // Zero-cost state transition - just change the type parameter
135 Operation {
136 ring: self.ring,
137 buffer: self.buffer,
138 fd: self.fd,
139 offset: self.offset,
140 op_type: self.op_type,
141 state: Completed { result },
142 }
143 }
144}