safer_ring/future/io_futures/
file_io.rs

1//! File I/O futures for read and write 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_io_operation};
11use crate::future::waker::WakerRegistry;
12use crate::operation::{Operation, Submitted};
13use crate::ring::Ring;
14
15/// Future for file read operations.
16///
17/// This future polls the completion queue until the read operation completes,
18/// then returns the number of bytes read and buffer ownership. The future
19/// ensures proper cleanup of waker registrations and handles both successful
20/// completions and error conditions.
21///
22/// # Type Parameters
23///
24/// * `'ring` - Lifetime of the io_uring Ring instance
25/// * `'buf` - Lifetime of the buffer used for the read operation
26///
27/// # Returns
28///
29/// Returns `(usize, Pin<&'buf mut [u8]>)` on success where:
30/// - `usize` is the number of bytes read
31/// - `Pin<&'buf mut [u8]>` is the buffer with 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 mut buffer = PinnedBuffer::with_capacity(1024);
42/// let file = File::open("example.txt")?;
43///
44/// // Buffer lifetime must outlive the operation
45/// let read_future = ring.read(file.as_raw_fd(), buffer.as_mut_slice())?;
46/// let (bytes_read, _buffer) = read_future.await?;
47///
48/// println!("Read {} bytes", bytes_read);
49/// # Ok(())
50/// # }
51/// ```
52pub struct ReadFuture<'ring, 'buf> {
53    // Option allows taking ownership during completion without Clone
54    operation: Option<Operation<'ring, 'buf, Submitted>>,
55    ring: &'ring mut Ring<'ring>,
56    // Rc allows sharing waker registry across multiple futures efficiently
57    waker_registry: Arc<WakerRegistry>,
58    // Explicit lifetime tracking for compile-time safety verification
59    _phantom: PhantomData<(&'ring (), &'buf ())>,
60}
61
62/// Future for file write operations.
63///
64/// This future polls the completion queue until the write operation completes,
65/// then returns the number of bytes written and buffer ownership. Like all
66/// I/O futures in this crate, it ensures proper resource cleanup and handles
67/// error conditions gracefully.
68///
69/// # Type Parameters
70///
71/// * `'ring` - Lifetime of the io_uring Ring instance  
72/// * `'buf` - Lifetime of the buffer containing data to write
73///
74/// # Returns
75///
76/// Returns `(usize, Pin<&'buf mut [u8]>)` on success where:
77/// - `usize` is the number of bytes written
78/// - `Pin<&'buf mut [u8]>` is the buffer that was written from
79///
80/// # Examples
81///
82/// ```rust,ignore
83/// # use safer_ring::{Ring, Operation, PinnedBuffer};
84/// # use std::fs::OpenOptions;
85/// # use std::os::unix::io::AsRawFd;
86/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
87/// let mut ring = Ring::new(32)?;
88/// let mut buffer = PinnedBuffer::from_slice(b"Hello, world!");
89/// let file = OpenOptions::new()
90///     .write(true)
91///     .create(true)
92///     .open("output.txt")?;
93///
94/// let write_future = ring.write(file.as_raw_fd(), buffer.as_mut_slice())?;
95/// let (bytes_written, _buffer) = write_future.await?;
96///
97/// println!("Wrote {} bytes", bytes_written);
98/// # Ok(())
99/// # }
100/// ```
101pub struct WriteFuture<'ring, 'buf> {
102    // Same structure as ReadFuture for consistency and shared macro usage
103    operation: Option<Operation<'ring, 'buf, Submitted>>,
104    ring: &'ring mut Ring<'ring>,
105    waker_registry: Arc<WakerRegistry>,
106    _phantom: PhantomData<(&'ring (), &'buf ())>,
107}
108
109impl<'ring, 'buf> ReadFuture<'ring, 'buf> {
110    pub(crate) fn new(
111        operation: Operation<'ring, 'buf, Submitted>,
112        ring: &'ring mut Ring<'ring>,
113        waker_registry: Arc<WakerRegistry>,
114    ) -> Self {
115        Self {
116            operation: Some(operation),
117            ring,
118            waker_registry,
119            _phantom: PhantomData,
120        }
121    }
122}
123
124impl<'ring, 'buf> WriteFuture<'ring, 'buf> {
125    pub(crate) fn new(
126        operation: Operation<'ring, 'buf, Submitted>,
127        ring: &'ring mut Ring<'ring>,
128        waker_registry: Arc<WakerRegistry>,
129    ) -> Self {
130        Self {
131            operation: Some(operation),
132            ring,
133            waker_registry,
134            _phantom: PhantomData,
135        }
136    }
137}
138
139impl<'ring, 'buf> Future for ReadFuture<'ring, 'buf> {
140    type Output = io::Result<(usize, StdPin<&'buf mut [u8]>)>;
141
142    fn poll(mut self: StdPin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
143        poll_io_operation!(self, cx, "ReadFuture")
144    }
145}
146
147impl<'ring, 'buf> Future for WriteFuture<'ring, 'buf> {
148    type Output = io::Result<(usize, StdPin<&'buf mut [u8]>)>;
149
150    fn poll(mut self: StdPin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
151        poll_io_operation!(self, cx, "WriteFuture")
152    }
153}
154
155impl<'ring, 'buf> Drop for ReadFuture<'ring, 'buf> {
156    fn drop(&mut self) {
157        impl_future_drop!(self);
158    }
159}
160
161impl<'ring, 'buf> Drop for WriteFuture<'ring, 'buf> {
162    fn drop(&mut self) {
163        impl_future_drop!(self);
164    }
165}