pub struct Operation<'ring, 'buf, S> { /* private fields */ }Expand description
Type-safe operation with compile-time state tracking.
The operation struct uses phantom types to track its current state and enforce valid state transitions at compile time. The lifetime parameters ensure that:
'ring: The operation cannot outlive the ring that will execute it'buf: The buffer cannot be dropped while the operation is in flight
§Type Parameters
'ring: Lifetime of the ring that will execute this operation'buf: Lifetime of the buffer used by this operationS: Current state of the operation (crate::operation::Building,crate::operation::Submitted, orcrate::operation::Completed<T>)
Implementations§
Source§impl<'ring, 'buf> Operation<'ring, 'buf, Building>
impl<'ring, 'buf> Operation<'ring, 'buf, Building>
Sourcepub fn new() -> Self
pub fn new() -> Self
Create a new operation in the building state.
The operation starts with default values and must be configured before it can be submitted.
§Example
let op = Operation::new()
.fd(0)
.offset(1024);Sourcepub fn read() -> Self
pub fn read() -> Self
Create a new read operation.
§Example
let mut buffer = vec![0u8; 1024];
let op = Operation::read()
.fd(0)
.buffer(Pin::new(buffer.as_mut_slice()));Sourcepub fn read_vectored() -> Self
pub fn read_vectored() -> Self
Create a new vectored read operation.
§Example
let mut buffer1 = vec![0u8; 512];
let mut buffer2 = vec![0u8; 512];
let buffers = vec![
Pin::new(buffer1.as_mut_slice()),
Pin::new(buffer2.as_mut_slice()),
];
let op = Operation::read_vectored()
.fd(0)
.buffers(buffers);Sourcepub fn write() -> Self
pub fn write() -> Self
Create a new write operation.
§Example
let mut buffer = b"Hello, world!".to_vec();
let op = Operation::write()
.fd(1)
.buffer(Pin::new(buffer.as_mut_slice()));Sourcepub fn write_vectored() -> Self
pub fn write_vectored() -> Self
Create a new vectored write operation.
§Example
let mut buffer1 = b"Hello, ".to_vec();
let mut buffer2 = b"world!".to_vec();
let buffers = vec![
Pin::new(buffer1.as_mut_slice()),
Pin::new(buffer2.as_mut_slice()),
];
let op = Operation::write_vectored()
.fd(1)
.buffers(buffers);Sourcepub fn send() -> Self
pub fn send() -> Self
Create a new send operation.
§Example
let mut buffer = b"Hello, client!".to_vec();
let op = Operation::send()
.fd(4)
.buffer(Pin::new(buffer.as_mut_slice()));Sourcepub fn recv() -> Self
pub fn recv() -> Self
Create a new receive operation.
§Example
let mut buffer = vec![0u8; 1024];
let op = Operation::recv()
.fd(4)
.buffer(Pin::new(buffer.as_mut_slice()));Sourcepub fn registered_fd(self, registered_fd: RegisteredFd) -> Self
pub fn registered_fd(self, registered_fd: RegisteredFd) -> Self
Set a registered file descriptor for this operation.
Using registered file descriptors can improve performance for frequently used file descriptors by avoiding kernel lookups.
§Arguments
registered_fd- A registered file descriptor
§Example
let mut registry = Registry::new();
let registered_fd = registry.register_fd(0)?;
let op = Operation::read().registered_fd(registered_fd);Sourcepub fn fixed_file(self, fixed_file: FixedFile) -> Self
pub fn fixed_file(self, fixed_file: FixedFile) -> Self
Set a fixed file for this operation.
Fixed files provide the best performance for frequently used files by avoiding both file descriptor lookups and translation overhead. The file must be pre-registered with the registry.
§Arguments
fixed_file- A fixed file from the registry
§Example
let mut registry = Registry::new();
let fixed_files = registry.register_fixed_files(vec![0, 1])?;
let op = Operation::read().fixed_file(fixed_files[0].clone());Sourcepub fn buffer(self, buffer: Pin<&'buf mut [u8]>) -> Self
pub fn buffer(self, buffer: Pin<&'buf mut [u8]>) -> Self
Set the buffer for this operation.
The buffer lifetime must be at least as long as the ring lifetime to ensure memory safety during the operation. The buffer must remain pinned in memory until the operation completes.
§Arguments
buffer- A pinned mutable slice that will be used for I/O
§Example
let mut data = vec![0u8; 4096];
let op = Operation::read()
.fd(0)
.buffer(Pin::new(data.as_mut_slice()));Sourcepub fn registered_buffer(self, registered_buffer: RegisteredBuffer) -> Self
pub fn registered_buffer(self, registered_buffer: RegisteredBuffer) -> Self
Set a registered buffer for this operation.
Using registered buffers can improve performance by avoiding kernel buffer validation and setup overhead.
§Arguments
registered_buffer- A registered buffer
§Example
let mut registry = Registry::new();
let buffer = Pin::new(Box::new([0u8; 1024]));
let registered_buffer = registry.register_buffer(buffer)?;
let op = Operation::read()
.fd(0)
.registered_buffer(registered_buffer);Sourcepub fn buffers(self, buffers: Vec<Pin<&'buf mut [u8]>>) -> Self
pub fn buffers(self, buffers: Vec<Pin<&'buf mut [u8]>>) -> Self
Set multiple buffers for vectored I/O operations.
This enables scatter-gather I/O where data can be read into or written from multiple non-contiguous buffers in a single operation.
§Arguments
buffers- A vector of pinned mutable slices
§Example
let mut buffer1 = vec![0u8; 512];
let mut buffer2 = vec![0u8; 512];
let buffers = vec![
Pin::new(buffer1.as_mut_slice()),
Pin::new(buffer2.as_mut_slice()),
];
let op = Operation::read_vectored()
.fd(0)
.buffers(buffers);Sourcepub fn offset(self, offset: u64) -> Self
pub fn offset(self, offset: u64) -> Self
Set the offset for this operation.
This is used for file operations to specify the position in the file. For socket operations, this parameter is typically ignored by the kernel.
§Arguments
offset- Byte offset in the file (0-based)
§Example
let op = Operation::read()
.fd(3)
.offset(1024); // Read starting at byte 1024Sourcepub fn get_offset(&self) -> u64
pub fn get_offset(&self) -> u64
Get the current offset.
Returns the byte offset for file operations, or 0 if not set.
Sourcepub fn validate(&self) -> Result<(), &'static str>
pub fn validate(&self) -> Result<(), &'static str>
Validate that the operation is ready for submission.
This checks that all required fields are set for the operation type. Using the type system’s knowledge about operation requirements for more efficient validation.
§Errors
Returns an error if:
- File descriptor is not set (< 0)
- Buffer is required but not set
- Vectored operation has empty buffer list
§Example
let op = Operation::read().fd(0);
assert!(op.validate().is_err()); // Missing bufferSource§impl<'ring, 'buf, T> Operation<'ring, 'buf, Completed<T>>
impl<'ring, 'buf, T> Operation<'ring, 'buf, Completed<T>>
Sourcepub fn into_result(self) -> (T, BufferType<'buf>)
pub fn into_result(self) -> (T, BufferType<'buf>)
Extract the result from the completed operation.
This consumes the operation and returns both the result and the buffer ownership, ensuring no resource leaks. This is the primary way to retrieve results from completed operations.
§Returns
A tuple containing:
- The operation result
- The buffer (if one was used), returned to the caller for reuse
§Example
let (bytes_read, buffer) = completed_op.into_result();
println!("Read {} bytes", bytes_read);
// Buffer can now be reused for another operationSourcepub fn into_result_with_buffer(self) -> (T, Option<Pin<&'buf mut [u8]>>)
pub fn into_result_with_buffer(self) -> (T, Option<Pin<&'buf mut [u8]>>)
Extract the result and return a pinned buffer if available.
This is a convenience method for operations that use regular pinned buffers.
For other buffer types, use into_result() instead.
Sourcepub fn into_result_with_vectored_buffers(
self,
) -> (T, Option<Vec<Pin<&'buf mut [u8]>>>)
pub fn into_result_with_vectored_buffers( self, ) -> (T, Option<Vec<Pin<&'buf mut [u8]>>>)
Extract the result and return vectored buffers if available.
This is a convenience method for vectored operations.
Sourcepub fn result(&self) -> &T
pub fn result(&self) -> &T
Get a reference to the result without consuming the operation.
This allows inspecting the result while keeping the operation intact.
Sourcepub fn op_type(&self) -> OperationType
pub fn op_type(&self) -> OperationType
Get the operation type.
Source§impl<'ring, 'buf, S: OperationState> Operation<'ring, 'buf, S>
impl<'ring, 'buf, S: OperationState> Operation<'ring, 'buf, S>
Sourcepub fn get_type(&self) -> OperationType
pub fn get_type(&self) -> OperationType
Get the operation type.
Returns the type of I/O operation this will perform.
Sourcepub fn has_buffer(&self) -> bool
pub fn has_buffer(&self) -> bool
Check if the operation has a buffer set.
Returns true if a buffer has been configured for this operation.
Source§impl<'ring, 'buf> Operation<'ring, 'buf, Submitted>
impl<'ring, 'buf> Operation<'ring, 'buf, Submitted>
Sourcepub fn id(&self) -> u64
pub fn id(&self) -> u64
Get the operation ID.
This ID is used to track the operation in the completion queue and match completions to their corresponding operations.
Sourcepub fn op_type(&self) -> OperationType
pub fn op_type(&self) -> OperationType
Get the operation type.
Sourcepub fn uses_registered_buffer(&self) -> bool
pub fn uses_registered_buffer(&self) -> bool
Check if this operation uses a registered buffer.
Sourcepub fn uses_registered_fd(&self) -> bool
pub fn uses_registered_fd(&self) -> bool
Check if this operation uses a registered file descriptor.
Sourcepub fn uses_fixed_file(&self) -> bool
pub fn uses_fixed_file(&self) -> bool
Check if this operation uses a fixed file.
Sourcepub fn is_vectored(&self) -> bool
pub fn is_vectored(&self) -> bool
Check if this operation is vectored.