Skip to content
500 changes: 500 additions & 0 deletions library/alloc/src/io/buf_read.rs

Large diffs are not rendered by default.

18 changes: 16 additions & 2 deletions library/alloc/src/io/cursor.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::alloc::Allocator;
use crate::boxed::Box;
use crate::io::{
self, BorrowedCursor, Cursor, ErrorKind, IoSlice, IoSliceMut, Read, WriteThroughCursor,
slice_write, slice_write_all, slice_write_all_vectored, slice_write_vectored,
self, BorrowedCursor, BufRead, Cursor, ErrorKind, IoSlice, IoSliceMut, Read,
WriteThroughCursor, slice_write, slice_write_all, slice_write_all_vectored,
slice_write_vectored,
};
use crate::string::String;
use crate::vec::Vec;
Expand Down Expand Up @@ -103,6 +104,19 @@ where
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> BufRead for Cursor<T>
where
T: AsRef<[u8]>,
{
fn fill_buf(&mut self) -> io::Result<&[u8]> {
Ok(Cursor::split(self).1)
}
fn consume(&mut self, amt: usize) {
self.set_position(self.position() + amt as u64);
}
}

/// Reserves the required space, and pads the vec with 0s if necessary.
fn reserve_and_pad<A: Allocator>(
pos_mut: &mut u64,
Expand Down
101 changes: 100 additions & 1 deletion library/alloc/src/io/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use crate::boxed::Box;
#[cfg(not(no_global_oom_handling))]
use crate::collections::VecDeque;
use crate::fmt;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write};
use crate::io::{
self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write,
};
use crate::string::String;
#[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))]
use crate::sync::Arc;
Expand Down Expand Up @@ -56,6 +58,38 @@ impl<R: Read + ?Sized> Read for &mut R {
(**self).read_buf_exact(cursor)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<B: BufRead + ?Sized> BufRead for &mut B {
#[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> {
(**self).fill_buf()
}

#[inline]
fn consume(&mut self, amt: usize) {
(**self).consume(amt)
}

#[inline]
fn has_data_left(&mut self) -> io::Result<bool> {
(**self).has_data_left()
}

#[inline]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
(**self).read_until(byte, buf)
}

#[inline]
fn skip_until(&mut self, byte: u8) -> io::Result<usize> {
(**self).skip_until(byte)
}

#[inline]
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
(**self).read_line(buf)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Read + ?Sized> Read for Box<R> {
Expand Down Expand Up @@ -177,6 +211,38 @@ impl<S: Seek + ?Sized> Seek for Box<S> {
(**self).seek_relative(offset)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<B: BufRead + ?Sized> BufRead for Box<B> {
#[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> {
(**self).fill_buf()
}

#[inline]
fn consume(&mut self, amt: usize) {
(**self).consume(amt)
}

#[inline]
fn has_data_left(&mut self) -> io::Result<bool> {
(**self).has_data_left()
}

#[inline]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
(**self).read_until(byte, buf)
}

#[inline]
fn skip_until(&mut self, byte: u8) -> io::Result<usize> {
(**self).skip_until(byte)
}

#[inline]
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
(**self).read_line(buf)
}
}

// =============================================================================
// In-memory buffer implementations
Expand Down Expand Up @@ -311,6 +377,19 @@ impl Read for &[u8] {
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for &[u8] {
#[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> {
Ok(*self)
}

#[inline]
fn consume(&mut self, amt: usize) {
*self = &self[amt..];
}
}

/// Write is implemented for `Vec<u8>` by appending to the vector.
/// The vector will grow as needed.
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -459,6 +538,26 @@ impl<A: Allocator> Read for VecDeque<u8, A> {
unsafe { io::append_to_string(buf, |buf| self.read_to_end(buf)) }
}
}

/// BufRead is implemented for `VecDeque<u8>` by reading bytes from the front of the `VecDeque`.
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vecdeque_buf_read", since = "1.75.0")]
impl<A: Allocator> BufRead for VecDeque<u8, A> {
/// Returns the contents of the "front" slice as returned by
/// [`as_slices`][`VecDeque::as_slices`]. If the contained byte slices of the `VecDeque` are
/// discontiguous, multiple calls to `fill_buf` will be needed to read the entire content.
#[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> {
let (front, _) = self.as_slices();
Ok(front)
}

#[inline]
fn consume(&mut self, amt: usize) {
self.drain(..amt);
}
}

/// Write is implemented for `VecDeque<u8>` by appending to the `VecDeque`, growing it as needed.
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vecdeque_read_write", since = "1.63.0")]
Expand Down
14 changes: 8 additions & 6 deletions library/alloc/src/io/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Traits, helpers, and type definitions for core I/O functionality.

mod buf_read;
mod cursor;
mod error;
mod impls;
Expand Down Expand Up @@ -27,17 +28,18 @@ pub use core::io::{
stream_len_default, take,
};

#[unstable(feature = "alloc_io", issue = "154046")]
pub use self::{
buf_read::BufRead,
read::{Read, read_to_string},
util::{Bytes, Lines, Split},
};
#[doc(hidden)]
#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")]
pub use self::{
read::{
DEFAULT_BUF_SIZE, append_to_string, default_read_buf, default_read_buf_exact,
default_read_exact, default_read_to_end, default_read_to_string, default_read_vectored,
},
util::{SpecReadByte, bytes, uninlined_slow_read_byte},
};
#[unstable(feature = "alloc_io", issue = "154046")]
pub use self::{
read::{Read, read_to_string},
util::Bytes,
util::{SpecReadByte, bytes, lines, split, uninlined_slow_read_byte},
};
4 changes: 3 additions & 1 deletion library/alloc/src/io/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ use crate::vec::Vec;
/// trait.
///
/// Please note that each call to [`read()`] may involve a system call, and
/// therefore, using something that implements `BufRead`, such as
/// `BufReader`, will be more efficient.
/// therefore, using something that implements [`BufRead`], such as
///
/// [`BufRead`]: crate::io::BufRead
///
/// Repeated calls to the reader use the same cursor, so for example
/// calling `read_to_end` twice on a `File` will only return the file's
Expand Down
Loading
Loading