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