async_std/io/buf_read/
mod.rs

1mod lines;
2mod read_line;
3mod read_until;
4mod split;
5
6pub use lines::Lines;
7pub use split::Split;
8
9use read_line::ReadLineFuture;
10use read_until::ReadUntilFuture;
11
12use std::mem;
13use std::pin::Pin;
14
15use crate::io;
16use crate::task::{Context, Poll};
17
18pub use futures_io::AsyncBufRead as BufRead;
19
20#[doc = r#"
21    Extension methods for [`BufRead`].
22
23    [`BufRead`]: ../trait.BufRead.html
24"#]
25pub trait BufReadExt: BufRead {
26    #[doc = r#"
27        Reads all bytes into `buf` until the delimiter `byte` or EOF is reached.
28
29        This function will read bytes from the underlying stream until the delimiter or EOF
30        is found. Once found, all bytes up to, and including, the delimiter (if found) will
31        be appended to `buf`.
32
33        If successful, this function will return the total number of bytes read.
34
35        # Examples
36
37        ```no_run
38        # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
39        #
40        use async_std::fs::File;
41        use async_std::io::BufReader;
42        use async_std::prelude::*;
43
44        let mut file = BufReader::new(File::open("a.txt").await?);
45
46        let mut buf = Vec::with_capacity(1024);
47        let n = file.read_until(b'\n', &mut buf).await?;
48        #
49        # Ok(()) }) }
50        ```
51
52        Multiple successful calls to `read_until` append all bytes up to and including to
53        `buf`:
54        ```
55        # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
56        #
57        use async_std::io::BufReader;
58        use async_std::prelude::*;
59
60        let from: &[u8] = b"append\nexample\n";
61        let mut reader = BufReader::new(from);
62        let mut buf = vec![];
63
64        let mut size = reader.read_until(b'\n', &mut buf).await?;
65        assert_eq!(size, 7);
66        assert_eq!(buf, b"append\n");
67
68        size += reader.read_until(b'\n', &mut buf).await?;
69        assert_eq!(size, from.len());
70
71        assert_eq!(buf, from);
72        #
73        # Ok(()) }) }
74        ```
75    "#]
76    fn read_until<'a>(
77        &'a mut self,
78        byte: u8,
79        buf: &'a mut Vec<u8>,
80    ) -> ReadUntilFuture<'a, Self>
81    where
82        Self: Unpin,
83    {
84        ReadUntilFuture {
85            reader: self,
86            byte,
87            buf,
88            read: 0,
89        }
90    }
91
92    #[doc = r#"
93        Reads all bytes and appends them into `buf` until a newline (the 0xA byte) is
94        reached.
95
96        This function will read bytes from the underlying stream until the newline
97        delimiter (the 0xA byte) or EOF is found. Once found, all bytes up to, and
98        including, the delimiter (if found) will be appended to `buf`.
99
100        If successful, this function will return the total number of bytes read.
101
102        If this function returns `Ok(0)`, the stream has reached EOF.
103
104        # Errors
105
106        This function has the same error semantics as [`read_until`] and will also return
107        an error if the read bytes are not valid UTF-8. If an I/O error is encountered then
108        `buf` may contain some bytes already read in the event that all data read so far
109        was valid UTF-8.
110
111        [`read_until`]: #method.read_until
112
113        # Examples
114
115        ```no_run
116        # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
117        #
118        use async_std::fs::File;
119        use async_std::io::BufReader;
120        use async_std::prelude::*;
121
122        let mut file = BufReader::new(File::open("a.txt").await?);
123
124        let mut buf = String::new();
125        file.read_line(&mut buf).await?;
126        #
127        # Ok(()) }) }
128        ```
129    "#]
130    fn read_line<'a>(
131        &'a mut self,
132        buf: &'a mut String,
133    ) -> ReadLineFuture<'a, Self>
134    where
135        Self: Unpin,
136    {
137        ReadLineFuture {
138            reader: self,
139            bytes: unsafe { mem::replace(buf.as_mut_vec(), Vec::new()) },
140            buf,
141            read: 0,
142        }
143    }
144
145    #[doc = r#"
146        Returns a stream over the lines of this byte stream.
147
148        The stream returned from this function will yield instances of
149        [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline byte
150        (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end.
151
152        [`io::Result`]: type.Result.html
153        [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
154
155        # Examples
156
157        ```no_run
158        # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
159        #
160        use async_std::fs::File;
161        use async_std::io::BufReader;
162        use async_std::prelude::*;
163
164        let file = File::open("a.txt").await?;
165        let mut lines = BufReader::new(file).lines();
166        let mut count = 0;
167
168        while let Some(line) = lines.next().await {
169            line?;
170            count += 1;
171        }
172        #
173        # Ok(()) }) }
174        ```
175    "#]
176    fn lines(self) -> Lines<Self>
177    where
178        Self: Unpin + Sized,
179    {
180        Lines {
181            reader: self,
182            buf: String::new(),
183            bytes: Vec::new(),
184            read: 0,
185        }
186    }
187
188    #[doc = r#"
189        Returns a stream over the contents of this reader split on the byte `byte`.
190
191        The stream returned from this function will return instances of
192        [`io::Result`]`<`[`Vec<u8>`]`>`. Each vector returned will *not* have
193        the delimiter byte at the end.
194
195        This function will yield errors whenever [`read_until`] would have
196        also yielded an error.
197
198        [`io::Result`]: type.Result.html
199        [`Vec<u8>`]: ../vec/struct.Vec.html
200        [`read_until`]: #method.read_until
201
202        # Examples
203
204        [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
205        this example, we use [`Cursor`] to iterate over all hyphen delimited
206        segments in a byte slice
207
208        [`Cursor`]: struct.Cursor.html
209
210        ```
211        # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
212        #
213        use async_std::prelude::*;
214        use async_std::io;
215
216        let cursor = io::Cursor::new(b"lorem-ipsum-dolor");
217
218        let mut split_iter = cursor.split(b'-').map(|l| l.unwrap());
219        assert_eq!(split_iter.next().await, Some(b"lorem".to_vec()));
220        assert_eq!(split_iter.next().await, Some(b"ipsum".to_vec()));
221        assert_eq!(split_iter.next().await, Some(b"dolor".to_vec()));
222        assert_eq!(split_iter.next().await, None);
223        #
224        # Ok(()) }) }
225        ```
226    "#]
227    fn split(self, byte: u8) -> Split<Self>
228    where
229        Self: Sized,
230    {
231        Split {
232            reader: self,
233            buf: Vec::new(),
234            delim: byte,
235            read: 0,
236        }
237    }
238}
239
240impl<T: BufRead + ?Sized> BufReadExt for T {}
241
242pub(crate) fn read_until_internal<R: BufReadExt + ?Sized>(
243    mut reader: Pin<&mut R>,
244    cx: &mut Context<'_>,
245    byte: u8,
246    buf: &mut Vec<u8>,
247    read: &mut usize,
248) -> Poll<io::Result<usize>> {
249    loop {
250        let (done, used) = {
251            let available = futures_core::ready!(reader.as_mut().poll_fill_buf(cx))?;
252            if let Some(i) = memchr::memchr(byte, available) {
253                buf.extend_from_slice(&available[..=i]);
254                (true, i + 1)
255            } else {
256                buf.extend_from_slice(available);
257                (false, available.len())
258            }
259        };
260        reader.as_mut().consume(used);
261        *read += used;
262        if done || used == 0 {
263            return Poll::Ready(Ok(mem::replace(read, 0)));
264        }
265    }
266}