Skip to main content

product_os_async_executor/
read_write.rs

1use alloc::boxed::Box;
2use alloc::string::String;
3use alloc::string::ToString;
4use alloc::vec::Vec;
5use bytes::{Buf, BufMut};
6/// Taken with modifications from hyper
7use core::fmt;
8use core::ops::{Deref, DerefMut};
9use core::pin::Pin;
10use core::task::{ready, Context, Poll};
11
12use core::future::Future;
13use core::marker::PhantomPinned;
14use core::mem;
15
16use crate::BoxError;
17
18/// A reference to a contiguous slice of memory for vectored I/O reads.
19///
20/// This is a `no_std`-compatible equivalent of `std::io::IoSliceMut`.
21#[derive(Debug)]
22pub struct IoSliceMut<'a>(&'a mut [u8]);
23
24impl<'a> IoSliceMut<'a> {
25    /// Creates a new `IoSliceMut` wrapping a mutable byte slice.
26    pub fn new(buf: &'a mut [u8]) -> Self {
27        Self(buf)
28    }
29}
30
31impl Deref for IoSliceMut<'_> {
32    type Target = [u8];
33    fn deref(&self) -> &[u8] {
34        self.0
35    }
36}
37
38impl DerefMut for IoSliceMut<'_> {
39    fn deref_mut(&mut self) -> &mut [u8] {
40        self.0
41    }
42}
43
44/// A reference to a contiguous slice of memory for vectored I/O writes.
45///
46/// This is a `no_std`-compatible equivalent of `std::io::IoSlice`.
47#[derive(Debug, Clone, Copy)]
48pub struct IoSlice<'a>(&'a [u8]);
49
50impl<'a> IoSlice<'a> {
51    /// Creates a new `IoSlice` wrapping a byte slice.
52    pub const fn new(buf: &'a [u8]) -> Self {
53        Self(buf)
54    }
55}
56
57impl Deref for IoSlice<'_> {
58    type Target = [u8];
59    fn deref(&self) -> &[u8] {
60        self.0
61    }
62}
63
64/// Trait for async reading operations.
65///
66/// This trait provides an interface for asynchronously reading bytes from a source.
67pub trait AsyncRead {
68    /// Attempts to read bytes into a buffer.
69    ///
70    /// # Errors
71    ///
72    /// Returns an error if the read operation fails.
73    fn poll_read(
74        self: Pin<&mut Self>,
75        cx: &mut Context<'_>,
76        buf: &mut [u8],
77    ) -> Poll<Result<usize, BoxError>>;
78
79    /// Attempts to read bytes into multiple buffers (vectored I/O).
80    ///
81    /// # Errors
82    ///
83    /// Returns an error if the read operation fails.
84    fn poll_read_vectored(
85        self: Pin<&mut Self>,
86        cx: &mut Context<'_>,
87        bufs: &mut [IoSliceMut<'_>],
88    ) -> Poll<Result<usize, BoxError>> {
89        for b in bufs {
90            if !b.is_empty() {
91                return self.poll_read(cx, b);
92            }
93        }
94
95        self.poll_read(cx, &mut [])
96    }
97}
98
99/// Trait for async writing operations.
100///
101/// This trait provides an interface for asynchronously writing bytes to a destination.
102pub trait AsyncWrite {
103    /// Attempts to write bytes from a buffer.
104    ///
105    /// # Errors
106    ///
107    /// Returns an error if the write operation fails.
108    fn poll_write(
109        self: Pin<&mut Self>,
110        cx: &mut Context<'_>,
111        buf: &[u8],
112    ) -> Poll<Result<usize, BoxError>>;
113
114    /// Flushes any buffered data.
115    ///
116    /// # Errors
117    ///
118    /// Returns an error if the flush operation fails.
119    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), BoxError>>;
120
121    /// Shuts down the writer.
122    ///
123    /// # Errors
124    ///
125    /// Returns an error if the shutdown operation fails.
126    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), BoxError>>;
127
128    /// Returns whether vectored writes are supported.
129    fn is_write_vectored(&self) -> bool {
130        false
131    }
132
133    /// Attempts to write bytes from multiple buffers (vectored I/O).
134    ///
135    /// # Errors
136    ///
137    /// Returns an error if the write operation fails.
138    fn poll_write_vectored(
139        self: Pin<&mut Self>,
140        cx: &mut Context<'_>,
141        bufs: &[IoSlice],
142    ) -> Poll<Result<usize, BoxError>> {
143        for b in bufs {
144            if !b.is_empty() {
145                return self.poll_write(cx, b);
146            }
147        }
148
149        self.poll_write(cx, &[])
150    }
151}
152
153/// A read buffer that tracks filled and initialized portions.
154///
155/// This buffer manages a `Vec<u8>` and keeps track of which bytes have been
156/// filled with data and which bytes have been initialized.
157pub struct ReadBuf {
158    raw: Vec<u8>,
159    filled: usize,
160    init: usize,
161}
162
163impl ReadBuf {
164    /// Creates a new `ReadBuf` from a mutable slice.
165    ///
166    /// The data is copied into an owned `Vec<u8>`. All bytes are considered
167    /// initialized but unfilled.
168    #[inline]
169    pub fn new(raw: &mut [u8]) -> Self {
170        let len = raw.len();
171        Self {
172            raw: raw.to_vec(),
173            filled: 0,
174            init: len,
175        }
176    }
177
178    /// Creates a new `ReadBuf` with uninitialized bytes.
179    ///
180    /// All bytes are considered uninitialized and unfilled.
181    #[inline]
182    pub const fn uninit(raw: Vec<u8>) -> Self {
183        Self {
184            raw,
185            filled: 0,
186            init: 0,
187        }
188    }
189
190    /// Returns a mutable reference to the underlying buffer.
191    #[inline]
192    pub fn raw(&mut self) -> &mut Vec<u8> {
193        &mut self.raw
194    }
195
196    /// Returns the filled portion of the buffer as a slice.
197    #[inline]
198    pub fn filled(&self) -> &[u8] {
199        &self.raw[..self.filled]
200    }
201
202    /// Returns a cursor over the unfilled portion of the buffer.
203    #[inline]
204    pub fn unfilled(&mut self) -> ReadBufCursor<'_> {
205        ReadBufCursor { buf: &mut *self }
206    }
207
208    /// Sets the number of initialized bytes.
209    ///
210    /// # Safety
211    ///
212    /// The caller must ensure that at least `n` bytes have been initialized.
213    #[inline]
214    #[allow(dead_code)]
215    pub(crate) unsafe fn set_init(&mut self, n: usize) {
216        self.init = self.init.max(n);
217    }
218
219    /// Sets the number of filled bytes.
220    ///
221    /// # Safety
222    ///
223    /// The caller must ensure that at least `n` bytes have been filled with valid data.
224    #[inline]
225    #[allow(dead_code)]
226    pub(crate) unsafe fn set_filled(&mut self, n: usize) {
227        self.filled = self.filled.max(n);
228    }
229
230    #[inline]
231    #[allow(dead_code)]
232    pub(crate) const fn len(&self) -> usize {
233        self.filled
234    }
235
236    #[inline]
237    #[allow(dead_code)]
238    pub(crate) const fn init_len(&self) -> usize {
239        self.init
240    }
241
242    /// Returns the remaining capacity in the buffer.
243    #[inline]
244    fn remaining(&self) -> usize {
245        self.capacity() - self.filled
246    }
247
248    /// Returns the total capacity of the buffer.
249    #[inline]
250    fn capacity(&self) -> usize {
251        self.raw.len()
252    }
253}
254
255impl core::fmt::Debug for ReadBuf {
256    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257        f.debug_struct("ReadBuf")
258            .field("filled", &self.filled)
259            .field("init", &self.init)
260            .field("capacity", &self.capacity())
261            .field("raw", &self.raw)
262            .finish()
263    }
264}
265
266/// Cursor over the unfilled portion of a read buffer.
267///
268/// This provides methods to advance and modify the unfilled portion of the buffer.
269#[derive(Debug)]
270pub struct ReadBufCursor<'a> {
271    buf: &'a mut ReadBuf,
272}
273
274impl ReadBufCursor<'_> {
275    /// Returns a mutable reference to the underlying buffer.
276    ///
277    /// # Safety
278    ///
279    /// The caller must ensure that the buffer is properly initialized.
280    #[inline]
281    pub unsafe fn as_mut(&mut self) -> &mut Vec<u8> {
282        &mut self.buf.raw
283    }
284
285    /// Returns the filled portion of the buffer.
286    #[inline]
287    pub fn filled(&self) -> &[u8] {
288        self.buf.filled()
289    }
290
291    /// Advances the cursor by `n` bytes.
292    ///
293    /// # Safety
294    ///
295    /// The caller must ensure that `n` bytes have been initialized in the buffer.
296    ///
297    /// # Panics
298    ///
299    /// Panics if advancing by `n` would cause an overflow.
300    #[inline]
301    pub unsafe fn advance(&mut self, n: usize) {
302        self.buf.filled = self.buf.filled.checked_add(n).expect("overflow");
303        self.buf.init = self.buf.filled.max(self.buf.init);
304    }
305
306    /// Returns the remaining capacity in the buffer.
307    #[inline]
308    pub fn remaining(&self) -> usize {
309        self.buf.remaining()
310    }
311
312    /// Copies bytes from the provided buffer into this cursor.
313    ///
314    /// # Panics
315    ///
316    /// Panics if the buffer doesn't have enough remaining capacity.
317    #[inline]
318    pub fn put_slice(&mut self, buf: &[u8]) {
319        assert!(
320            self.buf.remaining() >= buf.len(),
321            "buf.len() must fit in remaining()"
322        );
323
324        let amt = buf.len();
325        let end = self.buf.filled + amt;
326
327        self.buf.raw[self.buf.filled..end].copy_from_slice(buf);
328
329        if self.buf.init < end {
330            self.buf.init = end;
331        }
332        self.buf.filled = end;
333    }
334}
335
336macro_rules! deref_async_read {
337    () => {
338        fn poll_read(
339            mut self: Pin<&mut Self>,
340            cx: &mut Context<'_>,
341            buf: &mut [u8],
342        ) -> Poll<Result<usize, BoxError>> {
343            Pin::new(&mut **self).poll_read(cx, buf)
344        }
345    };
346}
347
348impl<T: ?Sized + AsyncRead + Unpin> AsyncRead for Box<T> {
349    deref_async_read!();
350}
351
352impl<T: ?Sized + AsyncRead + Unpin> AsyncRead for &mut T {
353    deref_async_read!();
354}
355
356impl<P> AsyncRead for Pin<P>
357where
358    P: DerefMut,
359    P::Target: AsyncRead,
360{
361    fn poll_read(
362        self: Pin<&mut Self>,
363        cx: &mut Context<'_>,
364        buf: &mut [u8],
365    ) -> Poll<Result<usize, BoxError>> {
366        pin_as_deref_mut(self).poll_read(cx, buf)
367    }
368}
369
370macro_rules! deref_async_write {
371    () => {
372        fn poll_write(
373            mut self: Pin<&mut Self>,
374            cx: &mut Context<'_>,
375            buf: &[u8],
376        ) -> Poll<Result<usize, BoxError>> {
377            Pin::new(&mut **self).poll_write(cx, buf)
378        }
379
380        fn poll_write_vectored(
381            mut self: Pin<&mut Self>,
382            cx: &mut Context<'_>,
383            bufs: &[IoSlice],
384        ) -> Poll<Result<usize, BoxError>> {
385            Pin::new(&mut **self).poll_write_vectored(cx, bufs)
386        }
387
388        fn is_write_vectored(&self) -> bool {
389            (**self).is_write_vectored()
390        }
391
392        fn poll_flush(
393            mut self: Pin<&mut Self>,
394            cx: &mut Context<'_>,
395        ) -> Poll<Result<(), BoxError>> {
396            Pin::new(&mut **self).poll_flush(cx)
397        }
398
399        fn poll_shutdown(
400            mut self: Pin<&mut Self>,
401            cx: &mut Context<'_>,
402        ) -> Poll<Result<(), BoxError>> {
403            Pin::new(&mut **self).poll_shutdown(cx)
404        }
405    };
406}
407
408impl<T: ?Sized + AsyncWrite + Unpin> AsyncWrite for Box<T> {
409    deref_async_write!();
410}
411
412impl<T: ?Sized + AsyncWrite + Unpin> AsyncWrite for &mut T {
413    deref_async_write!();
414}
415
416impl<P> AsyncWrite for Pin<P>
417where
418    P: DerefMut,
419    P::Target: AsyncWrite,
420{
421    fn poll_write(
422        self: Pin<&mut Self>,
423        cx: &mut Context<'_>,
424        buf: &[u8],
425    ) -> Poll<Result<usize, BoxError>> {
426        pin_as_deref_mut(self).poll_write(cx, buf)
427    }
428
429    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), BoxError>> {
430        pin_as_deref_mut(self).poll_flush(cx)
431    }
432
433    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), BoxError>> {
434        pin_as_deref_mut(self).poll_shutdown(cx)
435    }
436
437    fn is_write_vectored(&self) -> bool {
438        (**self).is_write_vectored()
439    }
440
441    fn poll_write_vectored(
442        self: Pin<&mut Self>,
443        cx: &mut Context<'_>,
444        bufs: &[IoSlice],
445    ) -> Poll<Result<usize, BoxError>> {
446        pin_as_deref_mut(self).poll_write_vectored(cx, bufs)
447    }
448}
449
450/// Polyfill for `Pin::as_deref_mut()`
451/// NOTE: `Pin::as_deref_mut()` is not yet stabilized as of Rust 1.81.
452/// This polyfill should be replaced once the method is stabilized.
453fn pin_as_deref_mut<P: DerefMut>(pin: Pin<&mut Pin<P>>) -> Pin<&mut P::Target> {
454    // SAFETY: we go directly from Pin<&mut Pin<P>> to Pin<&mut P::Target>, without moving or
455    // giving out the &mut Pin<P> in the process. See Pin::as_deref_mut() for more detail.
456    unsafe { pin.get_unchecked_mut() }.as_mut()
457}
458
459/// Polls reading from an `AsyncRead` into a buffer.
460///
461/// # Errors
462///
463/// Returns an error if the read operation fails.
464pub fn poll_read_buf<T: AsyncRead, B: Buf + BufMut>(
465    io: Pin<&mut T>,
466    cx: &mut Context<'_>,
467    buf: &mut B,
468) -> Poll<Result<usize, BoxError>> {
469    if !buf.has_remaining_mut() {
470        return Poll::Ready(Ok(0));
471    }
472
473    let dst = buf.chunk_mut();
474    // SAFETY: BufMut guarantees the returned UninitSlice is valid for writes
475    let dst_slice = unsafe { core::slice::from_raw_parts_mut(dst.as_mut_ptr(), dst.len()) };
476
477    let n = ready!(io.poll_read(cx, dst_slice)?);
478
479    // SAFETY: poll_read guarantees that n bytes have been written to the buffer
480    unsafe {
481        buf.advance_mut(n);
482    }
483
484    Poll::Ready(Ok(n))
485}
486
487/// Polls writing from a buffer to an `AsyncWrite`.
488///
489/// # Errors
490///
491/// Returns an error if the write operation fails.
492pub fn poll_write_buf<T: AsyncWrite, B: Buf + BufMut>(
493    io: Pin<&mut T>,
494    cx: &mut Context<'_>,
495    buf: &mut B,
496) -> Poll<Result<usize, BoxError>> {
497    if !buf.has_remaining() {
498        return Poll::Ready(Ok(0));
499    }
500
501    let n = if io.is_write_vectored() {
502        let slice = IoSlice::new(buf.chunk());
503        let slices = [slice];
504        ready!(io.poll_write_vectored(cx, &slices))?
505    } else {
506        ready!(io.poll_write(cx, buf.chunk()))?
507    };
508
509    buf.advance(n);
510
511    Poll::Ready(Ok(n))
512}
513
514/// Extension trait for `AsyncWrite` providing utility methods.
515pub trait AsyncWriteExt: AsyncWrite {
516    /// Writes all bytes from the source buffer to this writer.
517    ///
518    /// Calls `poll_write` repeatedly until the entire buffer has been written.
519    ///
520    /// # Errors
521    ///
522    /// Returns an error if writing fails or if zero bytes are written (indicating the writer is closed).
523    fn write_all<'a>(&'a mut self, src: &'a [u8]) -> WriteAll<'a, Self>
524    where
525        Self: Unpin,
526    {
527        write_all(self, src)
528    }
529}
530
531impl<T: AsyncWrite + ?Sized> AsyncWriteExt for T {}
532
533/// A future that writes all bytes from a buffer to a writer.
534///
535/// This is created by the [`AsyncWriteExt::write_all`] method.
536#[derive(Debug)]
537#[must_use = "futures do nothing unless you `.await` or poll them"]
538pub struct WriteAll<'a, W: ?Sized> {
539    writer: &'a mut W,
540    buf: &'a [u8],
541    _pin: PhantomPinned,
542}
543
544impl<'a, W: ?Sized> WriteAll<'a, W> {
545    #[allow(clippy::mut_mut)]
546    fn project(self: Pin<&mut Self>) -> (&mut &'a mut W, &mut &'a [u8]) {
547        // SAFETY: `writer` and `buf` are not structurally pinned (they are references).
548        // Only `_pin: PhantomPinned` is structurally pinned but we never move it.
549        let this = unsafe { self.get_unchecked_mut() };
550        (&mut this.writer, &mut this.buf)
551    }
552}
553
554pub(crate) fn write_all<'a, W>(writer: &'a mut W, buf: &'a [u8]) -> WriteAll<'a, W>
555where
556    W: AsyncWrite + Unpin + ?Sized,
557{
558    WriteAll {
559        writer,
560        buf,
561        _pin: PhantomPinned,
562    }
563}
564
565impl<W> Future for WriteAll<'_, W>
566where
567    W: AsyncWrite + Unpin + ?Sized,
568{
569    type Output = Result<(), BoxError>;
570
571    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), BoxError>> {
572        let (writer, buf) = self.project();
573        while !buf.is_empty() {
574            let n = ready!(Pin::new(&mut **writer).poll_write(cx, buf))?;
575            {
576                let (_, rest) = mem::take(buf).split_at(n);
577                *buf = rest;
578            }
579            if n == 0 {
580                return Poll::Ready(Err(Box::new(IoError(String::from("Write Zero")))));
581            }
582        }
583
584        Poll::Ready(Ok(()))
585    }
586}
587
588/// An I/O error with a message.
589#[derive(Debug)]
590pub struct IoError(pub String);
591
592impl IoError {
593    #[allow(dead_code)]
594    pub(crate) fn new(s: &str) -> Self {
595        Self(s.to_string())
596    }
597}
598
599impl fmt::Display for IoError {
600    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
601        write!(fmt, "{}", self.0)
602    }
603}
604
605impl core::error::Error for IoError {}