compio_io/read/
mod.rs

1#[cfg(feature = "allocator_api")]
2use std::alloc::Allocator;
3use std::{io::Cursor, ops::DerefMut, rc::Rc, sync::Arc};
4
5use compio_buf::{BufResult, IntoInner, IoBuf, 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;
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    ///
28    /// Implementor **MUST** update the buffer init via
29    /// [`SetBufInit::set_buf_init`] after reading, and no further update should
30    /// be made by caller.
31    ///
32    /// [`SetBufInit::set_buf_init`]: compio_buf::SetBufInit::set_buf_init
33    async fn read<B: IoBufMut>(&mut self, buf: B) -> BufResult<usize, B>;
34
35    /// Like `read`, except that it reads into a type implements
36    /// [`IoVectoredBufMut`].
37    ///
38    /// The default implementation will try to read into the buffers in order,
39    /// and stop whenever the reader returns an error, `Ok(0)`, or a length
40    /// less than the length of the buf passed in, meaning it's possible that
41    /// not all buffer space is filled. If guaranteed full read is desired,
42    /// it is recommended to use [`AsyncReadExt::read_vectored_exact`]
43    /// instead.
44    ///
45    /// # Caution
46    ///
47    /// Implementor **MUST** update the buffer init via
48    /// [`SetBufInit::set_buf_init`] after reading.
49    ///
50    /// [`SetBufInit::set_buf_init`]: compio_buf::SetBufInit::set_buf_init
51    async fn read_vectored<V: IoVectoredBufMut>(&mut self, buf: V) -> BufResult<usize, V> {
52        loop_read_vectored!(buf, iter, self.read(iter))
53    }
54}
55
56impl<A: AsyncRead + ?Sized> AsyncRead for &mut A {
57    #[inline(always)]
58    async fn read<T: IoBufMut>(&mut self, buf: T) -> BufResult<usize, T> {
59        (**self).read(buf).await
60    }
61
62    #[inline(always)]
63    async fn read_vectored<T: IoVectoredBufMut>(&mut self, buf: T) -> BufResult<usize, T> {
64        (**self).read_vectored(buf).await
65    }
66}
67
68impl<R: AsyncRead + ?Sized, #[cfg(feature = "allocator_api")] A: Allocator> AsyncRead
69    for t_alloc!(Box, R, A)
70{
71    #[inline(always)]
72    async fn read<T: IoBufMut>(&mut self, buf: T) -> BufResult<usize, T> {
73        (**self).read(buf).await
74    }
75
76    #[inline(always)]
77    async fn read_vectored<T: IoVectoredBufMut>(&mut self, buf: T) -> BufResult<usize, T> {
78        (**self).read_vectored(buf).await
79    }
80}
81
82impl AsyncRead for &[u8] {
83    #[inline]
84    async fn read<T: IoBufMut>(&mut self, mut buf: T) -> BufResult<usize, T> {
85        let len = slice_to_buf(self, &mut buf);
86        *self = &self[len..];
87        BufResult(Ok(len), buf)
88    }
89
90    async fn read_vectored<T: IoVectoredBufMut>(&mut self, mut buf: T) -> BufResult<usize, T> {
91        let mut this = *self; // An immutable slice to track the read position
92
93        for mut buf in buf.iter_buf_mut() {
94            let n = slice_to_buf(this, buf.deref_mut());
95            this = &this[n..];
96            if this.is_empty() {
97                break;
98            }
99        }
100
101        let len = self.len() - this.len();
102        *self = this;
103
104        BufResult(Ok(len), buf)
105    }
106}
107
108/// # AsyncReadAt
109///
110/// Async read with a ownership of a buffer and a position
111pub trait AsyncReadAt {
112    /// Like [`AsyncRead::read`], except that it reads at a specified position.
113    async fn read_at<T: IoBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T>;
114
115    /// Like [`AsyncRead::read_vectored`], except that it reads at a specified
116    /// position.
117    async fn read_vectored_at<T: IoVectoredBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
118        loop_read_vectored!(buf, iter, self.read_at(iter, pos))
119    }
120}
121
122macro_rules! impl_read_at {
123    (@ptr $($ty:ty),*) => {
124        $(
125            impl<A: AsyncReadAt + ?Sized> AsyncReadAt for $ty {
126                async fn read_at<T: IoBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
127                    (**self).read_at(buf, pos).await
128                }
129
130                async fn read_vectored_at<T: IoVectoredBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
131                    (**self).read_vectored_at(buf, pos).await
132                }
133            }
134        )*
135    };
136
137    (@ptra $($ty:ident),*) => {
138        $(
139            #[cfg(feature = "allocator_api")]
140            impl<R: AsyncReadAt + ?Sized, A: Allocator> AsyncReadAt for $ty<R, A> {
141                async fn read_at<T: IoBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
142                    (**self).read_at(buf, pos).await
143                }
144
145                async fn read_vectored_at<T: IoVectoredBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
146                    (**self).read_vectored_at(buf, pos).await
147                }
148            }
149            #[cfg(not(feature = "allocator_api"))]
150            impl_read_at!(@ptr $ty<A>);
151        )*
152    };
153
154    (@slice $($(const $len:ident =>)? $ty:ty), *) => {
155        $(
156            impl<$(const $len: usize)?> AsyncReadAt for $ty {
157                async fn read_at<T: IoBufMut>(&self, mut buf: T, pos: u64) -> BufResult<usize, T> {
158                    let pos = pos.min(self.len() as u64);
159                    let len = slice_to_buf(&self[pos as usize..], &mut buf);
160                    BufResult(Ok(len), buf)
161                }
162
163                async fn read_vectored_at<T:IoVectoredBufMut>(&self, mut buf: T, pos: u64) -> BufResult<usize, T> {
164                    let slice = &self[pos as usize..];
165                    let mut this = slice;
166
167                    for mut buf in buf.iter_buf_mut() {
168                        let n = slice_to_buf(this, buf.deref_mut());
169                        this = &this[n..];
170                        if this.is_empty() {
171                            break;
172                        }
173                    }
174
175                    BufResult(Ok(slice.len() - this.len()), buf)
176                }
177            }
178        )*
179    }
180}
181
182impl_read_at!(@ptr &A, &mut A);
183impl_read_at!(@ptra Box, Rc, Arc);
184impl_read_at!(@slice [u8], const LEN => [u8; LEN]);
185
186impl<#[cfg(feature = "allocator_api")] A: Allocator> AsyncReadAt for t_alloc!(Vec, u8, A) {
187    async fn read_at<T: IoBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
188        self.as_slice().read_at(buf, pos).await
189    }
190
191    async fn read_vectored_at<T: IoVectoredBufMut>(&self, buf: T, pos: u64) -> BufResult<usize, T> {
192        self.as_slice().read_vectored_at(buf, pos).await
193    }
194}
195
196impl<A: AsyncReadAt> AsyncRead for Cursor<A> {
197    #[inline]
198    async fn read<T: IoBufMut>(&mut self, buf: T) -> BufResult<usize, T> {
199        let pos = self.position();
200        let (n, buf) = buf_try!(self.get_ref().read_at(buf, pos).await);
201        self.set_position(pos + n as u64);
202        BufResult(Ok(n), buf)
203    }
204
205    #[inline]
206    async fn read_vectored<T: IoVectoredBufMut>(&mut self, buf: T) -> BufResult<usize, T> {
207        let pos = self.position();
208        let (n, buf) = buf_try!(self.get_ref().read_vectored_at(buf, pos).await);
209        self.set_position(pos + n as u64);
210        BufResult(Ok(n), buf)
211    }
212}