completion_io/
buf_read.rs

1use std::future;
2use std::io::{Cursor, Empty, Result};
3
4use completion_core::CompletionFuture;
5
6use crate::AsyncReadWith;
7
8/// Read bytes from a source that has an internal buffer asynchronously.
9///
10/// This is an asynchronous version of [`std::io::BufRead`].
11///
12/// You should not implement this trait manually, instead implement [`AsyncBufReadWith`].
13pub trait AsyncBufRead: for<'a> AsyncBufReadWith<'a> {}
14impl<T: for<'a> AsyncBufReadWith<'a> + ?Sized> AsyncBufRead for T {}
15
16/// Read bytes from a source that has an internal buffer asynchronously with a specific lifetime.
17pub trait AsyncBufReadWith<'a>: AsyncReadWith<'a> {
18    /// Future that returns the contents of the internal buffer.
19    type FillBufFuture: CompletionFuture<Output = Result<&'a [u8]>>;
20
21    /// Attempt to return the contents of the internal buffer, filling it with more data from the
22    /// inner reader if it is empty.
23    ///
24    /// This function is a lower-level call. It needs to be paired with the [`consume`] method to
25    /// function properly. When calling this method, none of the contents will be "read" in the
26    /// sense that later calling read may return the same contents. As such, [`consume`] must be
27    /// called with the number of bytes that are consumed from this buffer to ensure that the bytes
28    /// are never returned twice.
29    ///
30    /// An empty buffer returned indicates that the stream has reached EOF.
31    ///
32    /// # Errors
33    ///
34    /// This function will return an I/O error if the underlying reader was read, but returned an
35    /// error.
36    ///
37    /// [`consume`]: Self::consume
38    fn fill_buf(&'a mut self) -> Self::FillBufFuture;
39
40    /// Tell this buffer that `amt` bytes have been consumed from the buffer, and so should no
41    /// longer be returned in calls to [`read`](AsyncReadWith::read).
42    ///
43    /// This function is a lower-level call. It needs to be paired with the [`fill_buf`] method to
44    /// function properly. This function does not perform any I/O, it simply informs this object
45    /// that some amount of its buffer, returned from [`fill_buf`], has been consumed and should no
46    /// longer be returned. As such, this function may do odd things if [`fill_buf`] isn't called
47    /// before calling it.
48    ///
49    /// The `amt` must be `<=` the number of bytes in the buffer returned by [`fill_buf`].
50    ///
51    /// [`fill_buf`]: Self::fill_buf
52    fn consume(&mut self, amt: usize);
53}
54
55impl<'a, R: AsyncBufReadWith<'a> + ?Sized> AsyncBufReadWith<'a> for &mut R {
56    type FillBufFuture = R::FillBufFuture;
57
58    #[inline]
59    fn fill_buf(&'a mut self) -> Self::FillBufFuture {
60        (**self).fill_buf()
61    }
62    #[inline]
63    fn consume(&mut self, amt: usize) {
64        (**self).consume(amt)
65    }
66}
67
68impl<'a, R: AsyncBufReadWith<'a> + ?Sized> AsyncBufReadWith<'a> for Box<R> {
69    type FillBufFuture = R::FillBufFuture;
70
71    #[inline]
72    fn fill_buf(&'a mut self) -> Self::FillBufFuture {
73        (**self).fill_buf()
74    }
75    #[inline]
76    fn consume(&mut self, amt: usize) {
77        (**self).consume(amt)
78    }
79}
80
81impl<'a> AsyncBufReadWith<'a> for Empty {
82    type FillBufFuture = future::Ready<Result<&'a [u8]>>;
83
84    #[inline]
85    fn fill_buf(&'a mut self) -> Self::FillBufFuture {
86        future::ready(Ok(&[]))
87    }
88    #[inline]
89    fn consume(&mut self, _amt: usize) {}
90}
91
92impl<'a> AsyncBufReadWith<'a> for &[u8] {
93    type FillBufFuture = future::Ready<Result<&'a [u8]>>;
94
95    #[inline]
96    fn fill_buf(&'a mut self) -> Self::FillBufFuture {
97        future::ready(Ok(*self))
98    }
99    #[inline]
100    fn consume(&mut self, amt: usize) {
101        *self = &self[amt..];
102    }
103}
104
105impl<'a, T: AsRef<[u8]>> AsyncBufReadWith<'a> for Cursor<T> {
106    type FillBufFuture = future::Ready<Result<&'a [u8]>>;
107
108    #[inline]
109    fn fill_buf(&'a mut self) -> Self::FillBufFuture {
110        future::ready(std::io::BufRead::fill_buf(self))
111    }
112    #[inline]
113    fn consume(&mut self, amt: usize) {
114        std::io::BufRead::consume(self, amt);
115    }
116}
117
118#[cfg(test)]
119#[allow(dead_code, clippy::extra_unused_lifetimes)]
120fn test_impls_traits<'a>() {
121    fn assert_impls<R: AsyncBufRead>() {}
122
123    assert_impls::<Empty>();
124    assert_impls::<&'a mut Empty>();
125    assert_impls::<Box<Empty>>();
126    assert_impls::<&'a mut Box<&'a mut Empty>>();
127
128    assert_impls::<&'a [u8]>();
129    assert_impls::<&'a mut &'a [u8]>();
130
131    assert_impls::<Cursor<Vec<u8>>>();
132    assert_impls::<Cursor<&'a [u8]>>();
133    assert_impls::<&'a mut Cursor<&'a [u8]>>();
134}