async_std/io/buf_read/
mod.rs1mod 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}