X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=library%2Fstd%2Fsrc%2Fio%2Fmod.rs;h=00b85604a3f67bd5bd4dbd00b4f8313eb56aa5de;hb=d2852354dcf3378516a8ef0d005405c2a128c0a1;hp=4c154dbe01a5aa22835f4ee48c8e2f88ea1142aa;hpb=b3bcf4af747addb6af2fd031881c604435513c9e;p=rust.git diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 4c154dbe01a..00b85604a3f 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -252,7 +252,9 @@ mod tests; use crate::cmp; +use crate::convert::TryInto; use crate::fmt; +use crate::mem::replace; use crate::ops::{Deref, DerefMut}; use crate::ptr; use crate::slice; @@ -1044,6 +1046,32 @@ pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { /// Advance the internal cursor of the slice. /// + /// Also see [`IoSliceMut::advance_slices`] to advance the cursors of + /// multiple buffers. + /// + /// # Examples + /// + /// ``` + /// #![feature(io_slice_advance)] + /// + /// use std::io::IoSliceMut; + /// use std::ops::Deref; + /// + /// let mut data = [1; 8]; + /// let mut buf = IoSliceMut::new(&mut data); + /// + /// // Mark 3 bytes as read. + /// buf.advance(3); + /// assert_eq!(buf.deref(), [1; 5].as_ref()); + /// ``` + #[unstable(feature = "io_slice_advance", issue = "62726")] + #[inline] + pub fn advance(&mut self, n: usize) { + self.0.advance(n) + } + + /// Advance the internal cursor of the slices. + /// /// # Notes /// /// Elements in the slice may be modified if the cursor is not advanced to @@ -1070,13 +1098,13 @@ pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { /// ][..]; /// /// // Mark 10 bytes as read. - /// bufs = IoSliceMut::advance(bufs, 10); + /// IoSliceMut::advance_slices(&mut bufs, 10); /// assert_eq!(bufs[0].deref(), [2; 14].as_ref()); /// assert_eq!(bufs[1].deref(), [3; 8].as_ref()); /// ``` #[unstable(feature = "io_slice_advance", issue = "62726")] #[inline] - pub fn advance<'b>(bufs: &'b mut [IoSliceMut<'a>], n: usize) -> &'b mut [IoSliceMut<'a>] { + pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) { // Number of buffers to remove. let mut remove = 0; // Total length of all the to be removed buffers. @@ -1090,11 +1118,10 @@ pub fn advance<'b>(bufs: &'b mut [IoSliceMut<'a>], n: usize) -> &'b mut [IoSlice } } - let bufs = &mut bufs[remove..]; + *bufs = &mut replace(bufs, &mut [])[remove..]; if !bufs.is_empty() { - bufs[0].0.advance(n - accumulated_len) + bufs[0].advance(n - accumulated_len) } - bufs } } @@ -1153,6 +1180,32 @@ pub fn new(buf: &'a [u8]) -> IoSlice<'a> { /// Advance the internal cursor of the slice. /// + /// Also see [`IoSlice::advance_slices`] to advance the cursors of multiple + /// buffers. + /// + /// # Examples + /// + /// ``` + /// #![feature(io_slice_advance)] + /// + /// use std::io::IoSlice; + /// use std::ops::Deref; + /// + /// let mut data = [1; 8]; + /// let mut buf = IoSlice::new(&mut data); + /// + /// // Mark 3 bytes as read. + /// buf.advance(3); + /// assert_eq!(buf.deref(), [1; 5].as_ref()); + /// ``` + #[unstable(feature = "io_slice_advance", issue = "62726")] + #[inline] + pub fn advance(&mut self, n: usize) { + self.0.advance(n) + } + + /// Advance the internal cursor of the slices. + /// /// # Notes /// /// Elements in the slice may be modified if the cursor is not advanced to @@ -1179,12 +1232,12 @@ pub fn new(buf: &'a [u8]) -> IoSlice<'a> { /// ][..]; /// /// // Mark 10 bytes as written. - /// bufs = IoSlice::advance(bufs, 10); + /// IoSlice::advance_slices(&mut bufs, 10); /// assert_eq!(bufs[0].deref(), [2; 14].as_ref()); /// assert_eq!(bufs[1].deref(), [3; 8].as_ref()); #[unstable(feature = "io_slice_advance", issue = "62726")] #[inline] - pub fn advance<'b>(bufs: &'b mut [IoSlice<'a>], n: usize) -> &'b mut [IoSlice<'a>] { + pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) { // Number of buffers to remove. let mut remove = 0; // Total length of all the to be removed buffers. @@ -1198,11 +1251,10 @@ pub fn advance<'b>(bufs: &'b mut [IoSlice<'a>], n: usize) -> &'b mut [IoSlice<'a } } - let bufs = &mut bufs[remove..]; + *bufs = &mut replace(bufs, &mut [])[remove..]; if !bufs.is_empty() { - bufs[0].0.advance(n - accumulated_len) + bufs[0].advance(n - accumulated_len) } - bufs } } @@ -1511,7 +1563,7 @@ fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { fn write_all_vectored(&mut self, mut bufs: &mut [IoSlice<'_>]) -> Result<()> { // Guarantee that bufs is empty if it contains no data, // to avoid calling write_vectored if there is no data to be written. - bufs = IoSlice::advance(bufs, 0); + IoSlice::advance_slices(&mut bufs, 0); while !bufs.is_empty() { match self.write_vectored(bufs) { Ok(0) => { @@ -1520,7 +1572,7 @@ fn write_all_vectored(&mut self, mut bufs: &mut [IoSlice<'_>]) -> Result<()> { &"failed to write whole buffer", )); } - Ok(n) => bufs = IoSlice::advance(bufs, n), + Ok(n) => IoSlice::advance_slices(&mut bufs, n), Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), } @@ -1953,6 +2005,37 @@ pub trait BufRead: Read { #[stable(feature = "rust1", since = "1.0.0")] fn consume(&mut self, amt: usize); + /// Check if the underlying `Read` has any data left to be read. + /// + /// This function may fill the buffer to check for data, + /// so this functions returns `Result`, not `bool`. + /// + /// Default implementation calls `fill_buf` and checks that + /// returned slice is empty (which means that there is no data left, + /// since EOF is reached). + /// + /// Examples + /// + /// ``` + /// #![feature(buf_read_has_data_left)] + /// use std::io; + /// use std::io::prelude::*; + /// + /// let stdin = io::stdin(); + /// let mut stdin = stdin.lock(); + /// + /// while stdin.has_data_left().unwrap() { + /// let mut line = String::new(); + /// stdin.read_line(&mut line).unwrap(); + /// // work with line + /// println!("{:?}", line); + /// } + /// ``` + #[unstable(feature = "buf_read_has_data_left", reason = "recently added", issue = "86423")] + fn has_data_left(&mut self) -> Result { + self.fill_buf().map(|b| !b.is_empty()) + } + /// Read all bytes into `buf` until the delimiter `byte` or EOF is reached. /// /// This function will read bytes from the underlying stream until the @@ -2291,13 +2374,15 @@ fn consume(&mut self, amt: usize) { } impl SizeHint for Chain { + #[inline] fn lower_bound(&self) -> usize { SizeHint::lower_bound(&self.first) + SizeHint::lower_bound(&self.second) } + #[inline] fn upper_bound(&self) -> Option { match (SizeHint::upper_bound(&self.first), SizeHint::upper_bound(&self.second)) { - (Some(first), Some(second)) => Some(first + second), + (Some(first), Some(second)) => first.checked_add(second), _ => None, } } @@ -2502,6 +2587,21 @@ fn consume(&mut self, amt: usize) { } } +impl SizeHint for Take { + #[inline] + fn lower_bound(&self) -> usize { + cmp::min(SizeHint::lower_bound(&self.inner) as u64, self.limit) as usize + } + + #[inline] + fn upper_bound(&self) -> Option { + match SizeHint::upper_bound(&self.inner) { + Some(upper_bound) => Some(cmp::min(upper_bound as u64, self.limit) as usize), + None => self.limit.try_into().ok(), + } + } +} + /// An iterator over `u8` values of a reader. /// /// This struct is generally created by calling [`bytes`] on a reader. @@ -2546,15 +2646,53 @@ fn size_hint(&self) -> (usize, Option) { } impl SizeHint for T { + #[inline] default fn lower_bound(&self) -> usize { 0 } + #[inline] default fn upper_bound(&self) -> Option { None } } +impl SizeHint for &mut T { + #[inline] + fn lower_bound(&self) -> usize { + SizeHint::lower_bound(*self) + } + + #[inline] + fn upper_bound(&self) -> Option { + SizeHint::upper_bound(*self) + } +} + +impl SizeHint for Box { + #[inline] + fn lower_bound(&self) -> usize { + SizeHint::lower_bound(&**self) + } + + #[inline] + fn upper_bound(&self) -> Option { + SizeHint::upper_bound(&**self) + } +} + +impl SizeHint for &[u8] { + #[inline] + fn lower_bound(&self) -> usize { + self.len() + } + + #[inline] + fn upper_bound(&self) -> Option { + Some(self.len()) + } +} + /// An iterator over the contents of an instance of `BufRead` split on a /// particular byte. ///