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}