Skip to main content

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