safer_ring/operation/core.rs
1//! Core Operation struct definition and common functionality.
2//!
3//! This module contains the main Operation struct and methods that are
4//! available across all states.
5
6use std::marker::PhantomData;
7use std::os::unix::io::RawFd;
8use std::pin::Pin;
9
10use crate::operation::{OperationState, OperationType};
11use crate::registry::{FixedFile, RegisteredBuffer, RegisteredFd};
12
13/// Buffer type for operations.
14///
15/// This enum represents the different types of buffers that can be used
16/// with operations, supporting both regular pinned buffers and registered buffers.
17#[derive(Debug)]
18pub enum BufferType<'buf> {
19 /// No buffer (for operations like accept)
20 None,
21 /// Regular pinned buffer
22 Pinned(Pin<&'buf mut [u8]>),
23 /// Registered buffer with the registry
24 Registered(RegisteredBuffer),
25 /// Multiple pinned buffers for vectored I/O
26 Vectored(Vec<Pin<&'buf mut [u8]>>),
27}
28
29/// File descriptor type for operations.
30///
31/// This enum represents the different types of file descriptors that can be used
32/// with operations, supporting both regular file descriptors and registered ones.
33#[derive(Debug)]
34pub enum FdType {
35 /// Regular file descriptor
36 Raw(RawFd),
37 /// Registered file descriptor
38 Registered(RegisteredFd),
39 /// Fixed file (accessed by index)
40 Fixed(FixedFile),
41}
42
43/// Type-safe operation with compile-time state tracking.
44///
45/// The operation struct uses phantom types to track its current state and enforce
46/// valid state transitions at compile time. The lifetime parameters ensure that:
47/// - `'ring`: The operation cannot outlive the ring that will execute it
48/// - `'buf`: The buffer cannot be dropped while the operation is in flight
49///
50/// # Type Parameters
51///
52/// - `'ring`: Lifetime of the ring that will execute this operation
53/// - `'buf`: Lifetime of the buffer used by this operation
54/// - `S`: Current state of the operation ([`crate::operation::Building`], [`crate::operation::Submitted`], or [`crate::operation::Completed<T>`])
55#[derive(Debug)]
56pub struct Operation<'ring, 'buf, S> {
57 // PhantomData is zero-sized, so this doesn't add runtime overhead
58 pub(crate) ring: PhantomData<&'ring ()>,
59 // Buffer type supports different buffer configurations
60 pub(crate) buffer: BufferType<'buf>,
61 // File descriptor type supports both raw and registered fds
62 pub(crate) fd: FdType,
63 // u64 offset supports large files (>4GB) on all platforms
64 pub(crate) offset: u64,
65 pub(crate) op_type: OperationType,
66 pub(crate) state: S,
67}
68
69impl<'ring, 'buf, S: OperationState> Operation<'ring, 'buf, S> {
70 /// Get the operation type.
71 ///
72 /// Returns the type of I/O operation this will perform.
73 #[inline]
74 pub fn get_type(&self) -> OperationType {
75 self.op_type
76 }
77
78 /// Check if the operation has a buffer set.
79 ///
80 /// Returns `true` if a buffer has been configured for this operation.
81 #[inline]
82 pub fn has_buffer(&self) -> bool {
83 !matches!(self.buffer, BufferType::None)
84 }
85
86 /// Get the file descriptor for this operation.
87 ///
88 /// Returns the raw file descriptor, resolving registered fds if necessary.
89 #[inline]
90 pub fn get_fd(&self) -> RawFd {
91 match &self.fd {
92 FdType::Raw(fd) => *fd,
93 FdType::Registered(reg_fd) => reg_fd.raw_fd(),
94 FdType::Fixed(fixed_file) => fixed_file.raw_fd(),
95 }
96 }
97}