Operation

Struct Operation 

Source
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

Implementations§

Source§

impl<'ring, 'buf> Operation<'ring, 'buf, Building>

Source

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

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()));
Source

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

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()));
Source

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

pub fn accept() -> Self

Create a new accept operation.

§Example
let op = Operation::accept().fd(3); // listening socket fd
Source

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()));
Source

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()));
Source

pub fn fd(self, fd: RawFd) -> Self

Set the file descriptor for this operation.

This is required for all operations and must be a valid file descriptor.

§Arguments
  • fd - A valid file descriptor (>= 0)
§Example
let op = Operation::read().fd(0); // stdin
Source

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

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());
Source

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()));
Source

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

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

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 1024
Source

pub fn get_offset(&self) -> u64

Get the current offset.

Returns the byte offset for file operations, or 0 if not set.

Source

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 buffer
Source§

impl<'ring, 'buf, T> Operation<'ring, 'buf, Completed<T>>

Source

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 operation
Source

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.

Source

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.

Source

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.

Source

pub fn fd(&self) -> RawFd

Get the file descriptor for this operation.

Source

pub fn offset(&self) -> u64

Get the offset for this operation.

Source

pub fn op_type(&self) -> OperationType

Get the operation type.

Source§

impl<'ring, 'buf, S: OperationState> Operation<'ring, 'buf, S>

Source

pub fn get_type(&self) -> OperationType

Get the operation type.

Returns the type of I/O operation this will perform.

Source

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

pub fn get_fd(&self) -> RawFd

Get the file descriptor for this operation.

Returns the raw file descriptor, resolving registered fds if necessary.

Source§

impl<'ring, 'buf> Operation<'ring, 'buf, Submitted>

Source

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.

Source

pub fn fd(&self) -> RawFd

Get the file descriptor for this operation.

Source

pub fn offset(&self) -> u64

Get the offset for this operation.

Source

pub fn op_type(&self) -> OperationType

Get the operation type.

Source

pub fn uses_registered_buffer(&self) -> bool

Check if this operation uses a registered buffer.

Source

pub fn uses_registered_fd(&self) -> bool

Check if this operation uses a registered file descriptor.

Source

pub fn uses_fixed_file(&self) -> bool

Check if this operation uses a fixed file.

Source

pub fn is_vectored(&self) -> bool

Check if this operation is vectored.

Trait Implementations§

Source§

impl<'ring, 'buf, S: Debug> Debug for Operation<'ring, 'buf, S>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'ring, 'buf> Default for Operation<'ring, 'buf, Building>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<'ring, 'buf, S> Freeze for Operation<'ring, 'buf, S>
where S: Freeze,

§

impl<'ring, 'buf, S> RefUnwindSafe for Operation<'ring, 'buf, S>
where S: RefUnwindSafe,

§

impl<'ring, 'buf, S> Send for Operation<'ring, 'buf, S>
where S: Send,

§

impl<'ring, 'buf, S> Sync for Operation<'ring, 'buf, S>
where S: Sync,

§

impl<'ring, 'buf, S> Unpin for Operation<'ring, 'buf, S>
where S: Unpin,

§

impl<'ring, 'buf, S> !UnwindSafe for Operation<'ring, 'buf, S>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.