compio_io/read/
buf.rs

1use compio_buf::{BufResult, IntoInner, IoBuf, IoBufMut, IoVectoredBufMut, buf_try};
2
3use crate::{AsyncRead, IoResult, buffer::Buffer, util::DEFAULT_BUF_SIZE};
4/// # AsyncBufRead
5///
6/// Async read with buffered content.
7pub trait AsyncBufRead: AsyncRead {
8    /// Try fill the internal buffer with data
9    async fn fill_buf(&mut self) -> IoResult<&'_ [u8]>;
10
11    /// Mark how much data is read
12    fn consume(&mut self, amount: usize);
13}
14
15impl<A: AsyncBufRead + ?Sized> AsyncBufRead for &mut A {
16    async fn fill_buf(&mut self) -> IoResult<&'_ [u8]> {
17        (**self).fill_buf().await
18    }
19
20    fn consume(&mut self, amount: usize) {
21        (**self).consume(amount)
22    }
23}
24
25/// Wraps a reader and buffers input from [`AsyncRead`]
26///
27/// It can be excessively inefficient to work directly with a [`AsyncRead`]
28/// instance. A `BufReader<R>` performs large, infrequent reads on the
29/// underlying [`AsyncRead`] and maintains an in-memory buffer of the results.
30///
31/// `BufReader<R>` can improve the speed of programs that make *small* and
32/// *repeated* read calls to the same file or network socket. It does not
33/// help when reading very large amounts at once, or reading just one or a few
34/// times. It also provides no advantage when reading from a source that is
35/// already in memory, like a `Vec<u8>`.
36///
37/// When the `BufReader<R>` is dropped, the contents of its buffer will be
38/// discarded. Reading from the underlying reader after unwrapping the
39/// `BufReader<R>` with [`BufReader::into_inner`] can cause data loss.
40///
41/// # Caution
42///
43/// Due to the pass-by-ownership nature of completion-based IO, the buffer is
44/// passed to the inner reader when [`fill_buf`] is called. If the future
45/// returned by [`fill_buf`] is dropped before inner `read` is completed,
46/// `BufReader` will not be able to retrieve the buffer, causing panic on next
47/// [`fill_buf`] call.
48///
49/// [`fill_buf`]: #method.fill_buf
50#[derive(Debug)]
51pub struct BufReader<R> {
52    reader: R,
53    buf: Buffer,
54}
55
56impl<R> BufReader<R> {
57    /// Creates a new `BufReader` with a default buffer capacity. The default is
58    /// currently 8 KB, but may change in the future.
59    pub fn new(reader: R) -> Self {
60        Self::with_capacity(DEFAULT_BUF_SIZE, reader)
61    }
62
63    /// Creates a new `BufReader` with the specified buffer capacity.
64    pub fn with_capacity(cap: usize, reader: R) -> Self {
65        Self {
66            reader,
67            buf: Buffer::with_capacity(cap),
68        }
69    }
70}
71
72impl<R: AsyncRead> AsyncRead for BufReader<R> {
73    async fn read<B: IoBufMut>(&mut self, buf: B) -> BufResult<usize, B> {
74        let (mut slice, buf) = buf_try!(self.fill_buf().await, buf);
75        slice.read(buf).await.map_res(|res| {
76            self.consume(res);
77            res
78        })
79    }
80
81    async fn read_vectored<V: IoVectoredBufMut>(&mut self, buf: V) -> BufResult<usize, V> {
82        let (mut slice, buf) = buf_try!(self.fill_buf().await, buf);
83        slice.read_vectored(buf).await.map_res(|res| {
84            self.consume(res);
85            res
86        })
87    }
88}
89
90impl<R: AsyncRead> AsyncBufRead for BufReader<R> {
91    async fn fill_buf(&mut self) -> IoResult<&'_ [u8]> {
92        let Self { reader, buf } = self;
93
94        if buf.all_done() {
95            buf.reset()
96        }
97
98        if buf.need_fill() {
99            buf.with(|b| async move {
100                let len = b.buf_len();
101                let b = b.slice(len..);
102                reader.read(b).await.into_inner()
103            })
104            .await?;
105        }
106
107        Ok(buf.slice())
108    }
109
110    fn consume(&mut self, amount: usize) {
111        self.buf.advance(amount);
112    }
113}
114
115impl<R> IntoInner for BufReader<R> {
116    type Inner = R;
117
118    fn into_inner(self) -> Self::Inner {
119        self.reader
120    }
121}