|
| 1 | +mod lines; |
| 2 | +mod read_line; |
| 3 | +mod read_until; |
| 4 | + |
| 5 | +pub use lines::Lines; |
| 6 | +use read_line::ReadLineFuture; |
| 7 | +use read_until::ReadUntilFuture; |
| 8 | + |
1 | 9 | use std::mem; |
2 | 10 | use std::pin::Pin; |
3 | | -use std::str; |
4 | 11 |
|
5 | 12 | use cfg_if::cfg_if; |
6 | 13 | use futures_io::AsyncBufRead; |
7 | 14 |
|
8 | | -use crate::future::Future; |
9 | 15 | use crate::io; |
10 | 16 | use crate::task::{Context, Poll}; |
11 | 17 |
|
@@ -191,134 +197,6 @@ pub trait BufRead { |
191 | 197 |
|
192 | 198 | impl<T: AsyncBufRead + Unpin + ?Sized> BufRead for T {} |
193 | 199 |
|
194 | | -#[doc(hidden)] |
195 | | -#[allow(missing_debug_implementations)] |
196 | | -pub struct ReadUntilFuture<'a, T: Unpin + ?Sized> { |
197 | | - reader: &'a mut T, |
198 | | - byte: u8, |
199 | | - buf: &'a mut Vec<u8>, |
200 | | - read: usize, |
201 | | -} |
202 | | - |
203 | | -impl<T: AsyncBufRead + Unpin + ?Sized> Future for ReadUntilFuture<'_, T> { |
204 | | - type Output = io::Result<usize>; |
205 | | - |
206 | | - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
207 | | - let Self { |
208 | | - reader, |
209 | | - byte, |
210 | | - buf, |
211 | | - read, |
212 | | - } = &mut *self; |
213 | | - read_until_internal(Pin::new(reader), cx, *byte, buf, read) |
214 | | - } |
215 | | -} |
216 | | - |
217 | | -#[doc(hidden)] |
218 | | -#[allow(missing_debug_implementations)] |
219 | | -pub struct ReadLineFuture<'a, T: Unpin + ?Sized> { |
220 | | - reader: &'a mut T, |
221 | | - buf: &'a mut String, |
222 | | - bytes: Vec<u8>, |
223 | | - read: usize, |
224 | | -} |
225 | | - |
226 | | -impl<T: AsyncBufRead + Unpin + ?Sized> Future for ReadLineFuture<'_, T> { |
227 | | - type Output = io::Result<usize>; |
228 | | - |
229 | | - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
230 | | - let Self { |
231 | | - reader, |
232 | | - buf, |
233 | | - bytes, |
234 | | - read, |
235 | | - } = &mut *self; |
236 | | - let reader = Pin::new(reader); |
237 | | - |
238 | | - let ret = futures_core::ready!(read_until_internal(reader, cx, b'\n', bytes, read)); |
239 | | - if str::from_utf8(&bytes).is_err() { |
240 | | - Poll::Ready(ret.and_then(|_| { |
241 | | - Err(io::Error::new( |
242 | | - io::ErrorKind::InvalidData, |
243 | | - "stream did not contain valid UTF-8", |
244 | | - )) |
245 | | - })) |
246 | | - } else { |
247 | | - debug_assert!(buf.is_empty()); |
248 | | - debug_assert_eq!(*read, 0); |
249 | | - // Safety: `bytes` is a valid UTF-8 because `str::from_utf8` returned `Ok`. |
250 | | - mem::swap(unsafe { buf.as_mut_vec() }, bytes); |
251 | | - Poll::Ready(ret) |
252 | | - } |
253 | | - } |
254 | | -} |
255 | | - |
256 | | -/// A stream of lines in a byte stream. |
257 | | -/// |
258 | | -/// This stream is created by the [`lines`] method on types that implement [`BufRead`]. |
259 | | -/// |
260 | | -/// This type is an async version of [`std::io::Lines`]. |
261 | | -/// |
262 | | -/// [`lines`]: trait.BufRead.html#method.lines |
263 | | -/// [`BufRead`]: trait.BufRead.html |
264 | | -/// [`std::io::Lines`]: https://doc.rust-lang.org/nightly/std/io/struct.Lines.html |
265 | | -#[derive(Debug)] |
266 | | -pub struct Lines<R> { |
267 | | - reader: R, |
268 | | - buf: String, |
269 | | - bytes: Vec<u8>, |
270 | | - read: usize, |
271 | | -} |
272 | | - |
273 | | -impl<R: AsyncBufRead> futures_core::stream::Stream for Lines<R> { |
274 | | - type Item = io::Result<String>; |
275 | | - |
276 | | - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { |
277 | | - let Self { |
278 | | - reader, |
279 | | - buf, |
280 | | - bytes, |
281 | | - read, |
282 | | - } = unsafe { self.get_unchecked_mut() }; |
283 | | - let reader = unsafe { Pin::new_unchecked(reader) }; |
284 | | - let n = futures_core::ready!(read_line_internal(reader, cx, buf, bytes, read))?; |
285 | | - if n == 0 && buf.is_empty() { |
286 | | - return Poll::Ready(None); |
287 | | - } |
288 | | - if buf.ends_with('\n') { |
289 | | - buf.pop(); |
290 | | - if buf.ends_with('\r') { |
291 | | - buf.pop(); |
292 | | - } |
293 | | - } |
294 | | - Poll::Ready(Some(Ok(mem::replace(buf, String::new())))) |
295 | | - } |
296 | | -} |
297 | | - |
298 | | -pub fn read_line_internal<R: AsyncBufRead + ?Sized>( |
299 | | - reader: Pin<&mut R>, |
300 | | - cx: &mut Context<'_>, |
301 | | - buf: &mut String, |
302 | | - bytes: &mut Vec<u8>, |
303 | | - read: &mut usize, |
304 | | -) -> Poll<io::Result<usize>> { |
305 | | - let ret = futures_core::ready!(read_until_internal(reader, cx, b'\n', bytes, read)); |
306 | | - if str::from_utf8(&bytes).is_err() { |
307 | | - Poll::Ready(ret.and_then(|_| { |
308 | | - Err(io::Error::new( |
309 | | - io::ErrorKind::InvalidData, |
310 | | - "stream did not contain valid UTF-8", |
311 | | - )) |
312 | | - })) |
313 | | - } else { |
314 | | - debug_assert!(buf.is_empty()); |
315 | | - debug_assert_eq!(*read, 0); |
316 | | - // Safety: `bytes` is a valid UTF-8 because `str::from_utf8` returned `Ok`. |
317 | | - mem::swap(unsafe { buf.as_mut_vec() }, bytes); |
318 | | - Poll::Ready(ret) |
319 | | - } |
320 | | -} |
321 | | - |
322 | 200 | pub fn read_until_internal<R: AsyncBufRead + ?Sized>( |
323 | 201 | mut reader: Pin<&mut R>, |
324 | 202 | cx: &mut Context<'_>, |
|
0 commit comments