| 1 | use std::mem; |
| 2 | use std::pin::Pin; |
| 3 | use std::str; |
| 4 | use std::future::Future; |
| 5 | |
| 6 | use super::read_until_internal; |
| 7 | use crate::io::{self, BufRead}; |
| 8 | use crate::task::{Context, Poll}; |
| 9 | |
| 10 | #[doc (hidden)] |
| 11 | #[allow (missing_debug_implementations)] |
| 12 | pub struct ReadLineFuture<'a, T: Unpin + ?Sized> { |
| 13 | pub(crate) reader: &'a mut T, |
| 14 | pub(crate) buf: &'a mut String, |
| 15 | pub(crate) bytes: Vec<u8>, |
| 16 | pub(crate) read: usize, |
| 17 | } |
| 18 | |
| 19 | impl<T: BufRead + Unpin + ?Sized> Future for ReadLineFuture<'_, T> { |
| 20 | type Output = io::Result<usize>; |
| 21 | |
| 22 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
| 23 | let Self { |
| 24 | reader, |
| 25 | buf, |
| 26 | bytes, |
| 27 | read, |
| 28 | } = &mut *self; |
| 29 | let reader = Pin::new(reader); |
| 30 | |
| 31 | let ret = futures_core::ready!(read_until_internal(reader, cx, b' \n' , bytes, read)); |
| 32 | if str::from_utf8(&bytes).is_err() { |
| 33 | Poll::Ready(ret.and_then(|_| { |
| 34 | Err(io::Error::new( |
| 35 | io::ErrorKind::InvalidData, |
| 36 | "stream did not contain valid UTF-8" , |
| 37 | )) |
| 38 | })) |
| 39 | } else { |
| 40 | #[allow (clippy::debug_assert_with_mut_call)] |
| 41 | { |
| 42 | debug_assert!(buf.is_empty()); |
| 43 | debug_assert_eq!(*read, 0); |
| 44 | } |
| 45 | |
| 46 | // Safety: `bytes` is a valid UTF-8 because `str::from_utf8` returned `Ok`. |
| 47 | mem::swap(unsafe { buf.as_mut_vec() }, bytes); |
| 48 | Poll::Ready(ret) |
| 49 | } |
| 50 | } |
| 51 | } |
| 52 | |