Skip to main content

safer_ring/future/io_futures/
vectored_io.rs

1//! Vectored I/O futures for scatter-gather operations.
2
3use std::future::Future;
4use std::io;
5use std::marker::PhantomData;
6use std::pin::Pin as StdPin;
7use std::sync::Arc;
8use std::task::{Context, Poll};
9
10use super::common::{impl_future_drop, poll_vectored_operation};
11use crate::future::waker::WakerRegistry;
12use crate::operation::{Operation, Submitted};
13use crate::ring::Ring;
14
15/// Future for vectored read operations.
16///
17/// This future handles scatter-gather reads that operate on multiple buffers
18/// simultaneously, allowing for efficient I/O when data needs to be read into
19/// multiple non-contiguous memory regions. Returns the total bytes read and
20/// ownership of all buffers when the operation completes.
21///
22/// # Type Parameters
23///
24/// * `'ring` - Lifetime of the io_uring Ring instance
25/// * `'buf` - Lifetime of all buffers used for the vectored read
26///
27/// # Returns
28///
29/// Returns `(usize, Vec<Pin<&'buf mut [u8]>>)` on success where:
30/// - `usize` is the total number of bytes read across all buffers
31/// - `Vec<Pin<&'buf mut [u8]>>` are all the buffers containing read data
32///
33/// # Examples
34///
35/// ```rust,ignore
36/// # use safer_ring::{Ring, Operation, PinnedBuffer};
37/// # use std::fs::File;
38/// # use std::os::unix::io::AsRawFd;
39/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
40/// let mut ring = Ring::new(32)?;
41/// let file = File::open("data.bin")?;
42///
43/// // Create buffers for vectored read
44/// let mut header_buf = PinnedBuffer::with_capacity(512);
45/// let mut data_buf = PinnedBuffer::with_capacity(4096);
46/// let buffers = vec![header_buf.as_mut_slice(), data_buf.as_mut_slice()];
47///
48/// let read_future = ring.read_vectored(file.as_raw_fd(), buffers)?;
49/// let (total_bytes, _buffers) = read_future.await?;
50///
51/// println!("Read {} bytes total", total_bytes);
52/// # Ok(())
53/// # }
54/// ```
55pub struct VectoredReadFuture<'ring, 'buf> {
56    operation: Option<Operation<'ring, 'buf, Submitted>>,
57    ring: &'ring mut Ring<'ring>,
58    waker_registry: Arc<WakerRegistry>,
59    // Same lifetime structure as single-buffer operations for consistency
60    _phantom: PhantomData<(&'ring (), &'buf ())>,
61}
62
63/// Future for vectored write operations.
64///
65/// This future handles gather writes that operate on multiple buffers
66/// simultaneously, allowing for efficient I/O when data from multiple
67/// non-contiguous memory regions needs to be written in a single operation.
68/// Returns the total bytes written and ownership of all buffers when complete.
69///
70/// # Type Parameters
71///
72/// * `'ring` - Lifetime of the io_uring Ring instance
73/// * `'buf` - Lifetime of all buffers used for the vectored write
74///
75/// # Returns
76///
77/// Returns `(usize, Vec<Pin<&'buf mut [u8]>>)` on success where:
78/// - `usize` is the total number of bytes written from all buffers
79/// - `Vec<Pin<&'buf mut [u8]>>` are all the buffers that were written from
80///
81/// # Examples
82///
83/// ```rust,ignore
84/// # use safer_ring::{Ring, Operation, PinnedBuffer};
85/// # use std::fs::OpenOptions;
86/// # use std::os::unix::io::AsRawFd;
87/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
88/// let mut ring = Ring::new(32)?;
89/// let file = OpenOptions::new()
90///     .write(true)
91///     .create(true)
92///     .open("output.bin")?;
93///
94/// // Create buffers for vectored write
95/// let mut header_buf = PinnedBuffer::from_slice(b"HEADER: ");
96/// let mut data_buf = PinnedBuffer::from_slice(b"Important data content");
97/// let buffers = vec![header_buf.as_mut_slice(), data_buf.as_mut_slice()];
98///
99/// let write_future = ring.write_vectored(file.as_raw_fd(), buffers)?;
100/// let (total_bytes, _buffers) = write_future.await?;
101///
102/// println!("Wrote {} bytes total", total_bytes);
103/// # Ok(())
104/// # }
105/// ```
106pub struct VectoredWriteFuture<'ring, 'buf> {
107    operation: Option<Operation<'ring, 'buf, Submitted>>,
108    ring: &'ring mut Ring<'ring>,
109    waker_registry: Arc<WakerRegistry>,
110    _phantom: PhantomData<(&'ring (), &'buf ())>,
111}
112
113impl<'ring, 'buf> VectoredReadFuture<'ring, 'buf> {
114    pub(crate) fn new(
115        operation: Operation<'ring, 'buf, Submitted>,
116        ring: &'ring mut Ring<'ring>,
117        waker_registry: Arc<WakerRegistry>,
118    ) -> Self {
119        Self {
120            operation: Some(operation),
121            ring,
122            waker_registry,
123            _phantom: PhantomData,
124        }
125    }
126}
127
128impl<'ring, 'buf> VectoredWriteFuture<'ring, 'buf> {
129    pub(crate) fn new(
130        operation: Operation<'ring, 'buf, Submitted>,
131        ring: &'ring mut Ring<'ring>,
132        waker_registry: Arc<WakerRegistry>,
133    ) -> Self {
134        Self {
135            operation: Some(operation),
136            ring,
137            waker_registry,
138            _phantom: PhantomData,
139        }
140    }
141}
142
143impl<'ring, 'buf> Future for VectoredReadFuture<'ring, 'buf> {
144    type Output = io::Result<(usize, Vec<StdPin<&'buf mut [u8]>>)>;
145
146    fn poll(mut self: StdPin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
147        poll_vectored_operation!(self, cx, "VectoredReadFuture")
148    }
149}
150
151impl<'ring, 'buf> Future for VectoredWriteFuture<'ring, 'buf> {
152    type Output = io::Result<(usize, Vec<StdPin<&'buf mut [u8]>>)>;
153
154    fn poll(mut self: StdPin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
155        poll_vectored_operation!(self, cx, "VectoredWriteFuture")
156    }
157}
158
159impl<'ring, 'buf> Drop for VectoredReadFuture<'ring, 'buf> {
160    fn drop(&mut self) {
161        impl_future_drop!(self);
162    }
163}
164
165impl<'ring, 'buf> Drop for VectoredWriteFuture<'ring, 'buf> {
166    fn drop(&mut self) {
167        impl_future_drop!(self);
168    }
169}