compio_io\read/
mod.rs

1#[cfg(feature = "allocator_api")]
2use std::alloc::Allocator;
3use std::{io::Cursor, rc::Rc, sync::Arc};
4
5use compio_buf::{BufResult, IntoInner, IoBufMut, IoVectoredBufMut, buf_try, t_alloc};
6
7mod buf;
8#[macro_use]
9mod ext;
10mod managed;
11
12pub use buf::*;
13pub use ext::*;
14pub use managed::*;
15
16use crate::util::{slice_to_buf, slice_to_uninit};
17
18/// AsyncRead
19///
20/// Async read with a ownership of a buffer
21pub trait AsyncRead {
22    /// Read some bytes from this source into the [`IoBufMut`] buffer and return
23    /// a [`BufResult`], consisting of the buffer and a [`usize`] indicating
24    /// how many bytes were read.
25    ///
26    /// # Caution
27    /// - This function read data to the **beginning** of the buffer; that is,
28    ///   all existing data in the buffer will be overwritten. To read data to
29    ///   the end of the buffer, use [`AsyncReadExt::append`].
30    /// - Implementor **MUST** update the buffer init via [`SetLen::set_len`]
31    ///   after reading, and no further update should be made by caller.
32    ///
33    /// [`SetLen::set_len`]: compio_buf::SetLen::set_len
34    async fn read<B: IoBufMut>(&mut self, buf: B) -> BufResult<usize, B>;
35
36    /// Like `read`, except that it reads into a type implements
37    /// [`IoVectoredBufMut`].
38    ///
39    /// The default implementation will read only to first buffer in `buf` with
40    /// non-zero capacity and return, meaning it's possible and likely that not
41    /// all buffer space is filled. If guaranteed full read is desired,
42    /// it is recommended to use [`AsyncReadExt::read_vectored_exact`] instead.
43    ///
44    /// # Caution
45    ///
46    /// Implementor **MUST** update the buffer init via
47    /// [`SetLen::set_len`] after reading.
48    ///
49    /// [`SetLen::set_len`]: compio_buf::SetLen::set_len
50    async fn read_vectored<V: IoVectoredBufMut>(&mut self, buf: V) -> BufResult<usize, V> {
51        loop_read_vectored!(buf, iter, self.read(iter))
52    }
53}
54
55impl<A: AsyncRead + ?Sized> AsyncRead for &mut A {
56    #[inline(always)]
57    async fn read<T: IoBufMut>(&mut self, buf: T) -> BufResult<usize, T> {
58        (**self).read(buf).await
59    }
60
61    #[inline(always)]
62    async fn read_vectored<T: IoVectoredBufMut>(&mut self, buf: T) -> BufResult<usize, T> {
63        (**self).read_vectored(buf).await
64    }
65}
66
67impl<R: AsyncRead + ?Sized, #[cfg(feature = "allocator_api")] A: Allocator> AsyncRead
68    for t_alloc!(Box, R, A)
69{
70    #[inline(always)]
71    async fn read<T: IoBufMut>(&mut self, buf: T) -> BufResult<usize, T> {
72        (**self).read(buf).await
73    }
74
75    #[inline(always)]
76    async fn read_vectored<T: IoVectoredBufMut>(&mut self, buf: T) -> BufResult<usize, T> {
77        (**self).read_vectored(buf).await
78    }
79}
80
81impl AsyncRead for &[u8] {
82    #[inline]
83    async fn read<T: IoBufMut>(&mut self, mut buf: T) -> BufResult<usize, T> {
84        let len = slice_to_buf(self, &mut buf);
85        *self = &self[len..];
86        BufResult(Ok(len), buf)
87    }
88
89    async fn read_vectored<T: IoVectoredBufMut>(&mut self, mut buf: T) -> BufResult<usize, T> {
90        let mut this = *self; // An immutable slice to track the read position
91
92        for buf in buf.iter_uninit_slice() {
93            let n = slice_to_uninit(this, buf);
94            this = &this[n..];
95            if this.is_empty() {
96                break;
97            }
98        }
99
100        let len = self.len() - this.len();
101        *self = this;
102
103        unsafe {
104            buf.advance_vec_to(len);
105        }
106
107        BufResult(Ok(len), buf)
108    }
109}
110
111/// # AsyncReadAt
112///
113/// Async read with a ownership of a buffer and a position
114pub trait AsyncReadAt {
115    /// Like [`AsyncRead::read`], except that it reads at a specified position.
116    async fn read_at<T: IoBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T>;
117
118    /// Like [`AsyncRead::read_vectored`], except that it reads at a specified
119    /// position.
120    async fn read_vectored_at<T: IoVectoredBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
121        loop_read_vectored!(buf, iter, self.read_at(iter, pos))
122    }
123}
124
125macro_rules! impl_read_at {
126    (@ptr $($ty:ty),*) => {
127        $(
128            impl<A: AsyncReadAt + ?Sized> AsyncReadAt for $ty {
129                async fn read_at<T: IoBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
130                    (**self).read_at(buf, pos).await
131                }
132
133                async fn read_vectored_at<T: IoVectoredBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
134                    (**self).read_vectored_at(buf, pos).await
135                }
136            }
137        )*
138    };
139
140    (@ptra $($ty:ident),*) => {
141        $(
142            #[cfg(feature = "allocator_api")]
143            impl<R: AsyncReadAt + ?Sized, A: Allocator> AsyncReadAt for $ty<R, A> {
144                async fn read_at<T: IoBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
145                    (**self).read_at(buf, pos).await
146                }
147
148                async fn read_vectored_at<T: IoVectoredBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
149                    (**self).read_vectored_at(buf, pos).await
150                }
151            }
152            #[cfg(not(feature = "allocator_api"))]
153            impl_read_at!(@ptr $ty<A>);
154        )*
155    };
156
157    (@slice $($(const $len:ident =>)? $ty:ty), *) => {
158        $(
159            impl<$(const $len: usize)?> AsyncReadAt for $ty {
160                async fn read_at<T: IoBufMut>(&self, mut buf: T, pos: u64) -> BufResult<usize, T> {
161                    let pos = pos.min(self.len() as u64);
162                    let len = slice_to_buf(&self[pos as usize..], &mut buf);
163                    BufResult(Ok(len), buf)
164                }
165
166                async fn read_vectored_at<T:IoVectoredBufMut>(&self, mut buf: T, pos: u64) -> BufResult<usize, T> {
167                    let slice = &self[pos as usize..];
168                    let mut this = slice;
169
170                    for buf in buf.iter_uninit_slice() {
171                        let n = slice_to_uninit(this, buf);
172                        this = &this[n..];
173                        if this.is_empty() {
174                            break;
175                        }
176                    }
177
178                    let len = slice.len() - this.len();
179                    unsafe {
180                        buf.advance_vec_to(len);
181                    }
182
183                    BufResult(Ok(len), buf)
184                }
185            }
186        )*
187    }
188}
189
190impl_read_at!(@ptr &A, &mut A);
191impl_read_at!(@ptra Box, Rc, Arc);
192impl_read_at!(@slice [u8], const LEN => [u8; LEN]);
193
194impl<#[cfg(feature = "allocator_api")] A: Allocator> AsyncReadAt for t_alloc!(Vec, u8, A) {
195    async fn read_at<T: IoBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
196        self.as_slice().read_at(buf, pos).await
197    }
198
199    async fn read_vectored_at<T: IoVectoredBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
200        self.as_slice().read_vectored_at(buf, pos).await
201    }
202}
203
204impl<A: AsyncReadAt> AsyncRead for Cursor<A> {
205    #[inline]
206    async fn read<T: IoBufMut>(&mut self, buf: T) -> BufResult<usize, T> {
207        let pos = self.position();
208        let (n, buf) = buf_try!(self.get_ref().read_at(buf, pos).await);
209        self.set_position(pos + n as u64);
210        BufResult(Ok(n), buf)
211    }
212
213    #[inline]
214    async fn read_vectored<T: IoVectoredBufMut>(&mut self, buf: T) -> BufResult<usize, T> {
215        let pos = self.position();
216        let (n, buf) = buf_try!(self.get_ref().read_vectored_at(buf, pos).await);
217        self.set_position(pos + n as u64);
218        BufResult(Ok(n), buf)
219    }
220}