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;
/// 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
/// ][..];
///
/// // 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.
}
}
- 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
}
}
/// 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
/// ][..];
///
/// // 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.
}
}
- 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
}
}
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) => {
&"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),
}
#[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<bool>`, 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<bool> {
+ 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
}
impl<T, U> SizeHint for Chain<T, U> {
+ #[inline]
fn lower_bound(&self) -> usize {
SizeHint::lower_bound(&self.first) + SizeHint::lower_bound(&self.second)
}
+ #[inline]
fn upper_bound(&self) -> Option<usize> {
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,
}
}
}
}
+impl<T> SizeHint for Take<T> {
+ #[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<usize> {
+ 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.
}
impl<T> SizeHint for T {
+ #[inline]
default fn lower_bound(&self) -> usize {
0
}
+ #[inline]
default fn upper_bound(&self) -> Option<usize> {
None
}
}
+impl<T> SizeHint for &mut T {
+ #[inline]
+ fn lower_bound(&self) -> usize {
+ SizeHint::lower_bound(*self)
+ }
+
+ #[inline]
+ fn upper_bound(&self) -> Option<usize> {
+ SizeHint::upper_bound(*self)
+ }
+}
+
+impl<T> SizeHint for Box<T> {
+ #[inline]
+ fn lower_bound(&self) -> usize {
+ SizeHint::lower_bound(&**self)
+ }
+
+ #[inline]
+ fn upper_bound(&self) -> Option<usize> {
+ SizeHint::upper_bound(&**self)
+ }
+}
+
+impl SizeHint for &[u8] {
+ #[inline]
+ fn lower_bound(&self) -> usize {
+ self.len()
+ }
+
+ #[inline]
+ fn upper_bound(&self) -> Option<usize> {
+ Some(self.len())
+ }
+}
+
/// An iterator over the contents of an instance of `BufRead` split on a
/// particular byte.
///
assert!(s.next().is_none());
}
+ #[test]
+ fn buf_read_has_data_left() {
+ let mut buf = Cursor::new(&b"abcd"[..]);
+ assert!(buf.has_data_left().unwrap());
+ buf.read_exact(&mut [0; 2]).unwrap();
+ assert!(buf.has_data_left().unwrap());
+ buf.read_exact(&mut [0; 2]).unwrap();
+ assert!(!buf.has_data_left().unwrap());
+ }
+
#[test]
fn read_to_end() {
let mut c = Cursor::new(&b""[..]);
assert_eq!(size_hint, (0, Some(0)));
}
+#[test]
+fn slice_size_hint() {
+ let size_hint = (&[1, 2, 3]).bytes().size_hint();
+ assert_eq!(size_hint, (3, Some(3)));
+}
+
+#[test]
+fn take_size_hint() {
+ let size_hint = (&[1, 2, 3]).take(2).bytes().size_hint();
+ assert_eq!(size_hint, (2, Some(2)));
+
+ let size_hint = (&[1, 2, 3]).take(4).bytes().size_hint();
+ assert_eq!(size_hint, (3, Some(3)));
+
+ let size_hint = io::repeat(0).take(3).bytes().size_hint();
+ assert_eq!(size_hint, (3, Some(3)));
+}
+
#[test]
fn chain_empty_size_hint() {
let chain = io::empty().chain(io::empty());
let chain = buf_reader_1.chain(buf_reader_2);
let size_hint = chain.bytes().size_hint();
- assert_eq!(size_hint, (testdata.len(), None));
+ assert_eq!(size_hint, (testdata.len(), Some(testdata.len())));
}
#[test]
}
#[test]
-fn io_slice_mut_advance() {
+fn io_slice_mut_advance_slices() {
let mut buf1 = [1; 8];
let mut buf2 = [2; 16];
let mut buf3 = [3; 8];
][..];
// Only in a single buffer..
- bufs = IoSliceMut::advance(bufs, 1);
+ IoSliceMut::advance_slices(&mut bufs, 1);
assert_eq!(bufs[0].deref(), [1; 7].as_ref());
assert_eq!(bufs[1].deref(), [2; 16].as_ref());
assert_eq!(bufs[2].deref(), [3; 8].as_ref());
// Removing a buffer, leaving others as is.
- bufs = IoSliceMut::advance(bufs, 7);
+ IoSliceMut::advance_slices(&mut bufs, 7);
assert_eq!(bufs[0].deref(), [2; 16].as_ref());
assert_eq!(bufs[1].deref(), [3; 8].as_ref());
// Removing a buffer and removing from the next buffer.
- bufs = IoSliceMut::advance(bufs, 18);
+ IoSliceMut::advance_slices(&mut bufs, 18);
assert_eq!(bufs[0].deref(), [3; 6].as_ref());
}
#[test]
-fn io_slice_mut_advance_empty_slice() {
- let empty_bufs = &mut [][..];
+fn io_slice_mut_advance_slices_empty_slice() {
+ let mut empty_bufs = &mut [][..];
// Shouldn't panic.
- IoSliceMut::advance(empty_bufs, 1);
+ IoSliceMut::advance_slices(&mut empty_bufs, 1);
}
#[test]
-fn io_slice_mut_advance_beyond_total_length() {
+fn io_slice_mut_advance_slices_beyond_total_length() {
let mut buf1 = [1; 8];
let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..];
// Going beyond the total length should be ok.
- bufs = IoSliceMut::advance(bufs, 9);
+ IoSliceMut::advance_slices(&mut bufs, 9);
assert!(bufs.is_empty());
}
#[test]
-fn io_slice_advance() {
+fn io_slice_advance_slices() {
let buf1 = [1; 8];
let buf2 = [2; 16];
let buf3 = [3; 8];
let mut bufs = &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..];
// Only in a single buffer..
- bufs = IoSlice::advance(bufs, 1);
+ IoSlice::advance_slices(&mut bufs, 1);
assert_eq!(bufs[0].deref(), [1; 7].as_ref());
assert_eq!(bufs[1].deref(), [2; 16].as_ref());
assert_eq!(bufs[2].deref(), [3; 8].as_ref());
// Removing a buffer, leaving others as is.
- bufs = IoSlice::advance(bufs, 7);
+ IoSlice::advance_slices(&mut bufs, 7);
assert_eq!(bufs[0].deref(), [2; 16].as_ref());
assert_eq!(bufs[1].deref(), [3; 8].as_ref());
// Removing a buffer and removing from the next buffer.
- bufs = IoSlice::advance(bufs, 18);
+ IoSlice::advance_slices(&mut bufs, 18);
assert_eq!(bufs[0].deref(), [3; 6].as_ref());
}
#[test]
-fn io_slice_advance_empty_slice() {
- let empty_bufs = &mut [][..];
+fn io_slice_advance_slices_empty_slice() {
+ let mut empty_bufs = &mut [][..];
// Shouldn't panic.
- IoSlice::advance(empty_bufs, 1);
+ IoSlice::advance_slices(&mut empty_bufs, 1);
}
#[test]
-fn io_slice_advance_beyond_total_length() {
+fn io_slice_advance_slices_beyond_total_length() {
let buf1 = [1; 8];
let mut bufs = &mut [IoSlice::new(&buf1)][..];
// Going beyond the total length should be ok.
- bufs = IoSlice::advance(bufs, 9);
+ IoSlice::advance_slices(&mut bufs, 9);
assert!(bufs.is_empty());
}