blob: bba1c2b8c8a45f89af924f0b97236c491a98df80 [file] [edit]
use core::slice::memchr;
use crate::io::{ErrorKind, Lines, Read, Result, Split, append_to_string, lines, split};
use crate::string::String;
use crate::vec::Vec;
/// A `BufRead` is a type of [`Read`]er which has an internal buffer, allowing it
/// to perform extra ways of reading.
///
/// For example, reading line-by-line is inefficient without using a buffer, so
/// if you want to read by line, you'll need `BufRead`, which includes a
/// [`read_line`] method as well as a [`lines`] iterator.
///
/// # Examples
///
/// A locked standard input implements `BufRead`:
///
/// ```no_run
/// use std::io;
/// use std::io::prelude::*;
///
/// let stdin = io::stdin();
/// for line in stdin.lock().lines() {
/// println!("{}", line?);
/// }
/// # std::io::Result::Ok(())
/// ```
///
/// If you have something that implements [`Read`], you can use the `BufReader`
/// type to turn it into a `BufRead`.
///
/// For example, `File` implements [`Read`], but not `BufRead`.
/// `BufReader` to the rescue!
///
/// [`read_line`]: BufRead::read_line
/// [`lines`]: BufRead::lines
///
/// ```no_run
/// use std::io::{self, BufReader};
/// use std::io::prelude::*;
/// use std::fs::File;
///
/// fn main() -> io::Result<()> {
/// let f = File::open("foo.txt")?;
/// let f = BufReader::new(f);
///
/// for line in f.lines() {
/// let line = line?;
/// println!("{line}");
/// }
///
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "IoBufRead")]
pub trait BufRead: Read {
/// Returns the contents of the internal buffer, filling it with more data, via [`Read`] methods, if empty.
///
/// This is a lower-level method and is meant to be used together with [`consume`],
/// which can be used to mark bytes that should not be returned by subsequent calls to `read`.
///
/// [`consume`]: BufRead::consume
///
/// Returns an empty buffer when the stream has reached EOF.
///
/// # Errors
///
/// This function will return an I/O error if a [`Read`] method was called, but returned an error.
///
/// # Examples
///
/// A locked standard input implements `BufRead`:
///
/// ```no_run
/// use std::io;
/// use std::io::prelude::*;
///
/// let stdin = io::stdin();
/// let mut stdin = stdin.lock();
///
/// let buffer = stdin.fill_buf()?;
///
/// // work with buffer
/// println!("{buffer:?}");
///
/// // mark the bytes we worked with as read
/// let length = buffer.len();
/// stdin.consume(length);
/// # std::io::Result::Ok(())
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn fill_buf(&mut self) -> Result<&[u8]>;
/// Marks the given `amount` of additional bytes from the internal buffer as having been read.
/// Subsequent calls to `read` only return bytes that have not been marked as read.
///
/// This is a lower-level method and is meant to be used together with [`fill_buf`],
/// which can be used to fill the internal buffer via [`Read`] methods.
///
/// It is a logic error if `amount` exceeds the number of unread bytes in the internal buffer, which is returned by [`fill_buf`].
///
/// # Examples
///
/// Since `consume()` is meant to be used with [`fill_buf`],
/// that method's example includes an example of `consume()`.
///
/// [`fill_buf`]: BufRead::fill_buf
#[stable(feature = "rust1", since = "1.0.0")]
fn consume(&mut self, amount: usize);
/// Checks if there is any data left to be `read`.
///
/// This function may fill the buffer to check for data,
/// so this function returns `Result<bool>`, not `bool`.
///
/// The default implementation calls `fill_buf` and checks that the
/// returned slice is empty (which means that there is no data left,
/// since EOF is reached).
///
/// # Errors
///
/// This function will return an I/O error if a [`Read`] method was called, but returned an error.
///
/// 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()? {
/// let mut line = String::new();
/// stdin.read_line(&mut line)?;
/// // work with line
/// println!("{line:?}");
/// }
/// # std::io::Result::Ok(())
/// ```
#[unstable(feature = "buf_read_has_data_left", issue = "86423")]
fn has_data_left(&mut self) -> Result<bool> {
self.fill_buf().map(|b| !b.is_empty())
}
/// Reads all bytes into `buf` until the delimiter `byte` or EOF is reached.
///
/// This function will read bytes from the underlying stream until the
/// delimiter or EOF is found. Once found, all bytes up to, and including,
/// the delimiter (if found) will be appended to `buf`.
///
/// If successful, this function will return the total number of bytes read.
///
/// This function is blocking and should be used carefully: it is possible for
/// an attacker to continuously send bytes without ever sending the delimiter
/// or EOF.
///
/// # Errors
///
/// This function will ignore all instances of [`ErrorKind::Interrupted`] and
/// will otherwise return any errors returned by [`fill_buf`].
///
/// If an I/O error is encountered then all bytes read so far will be
/// present in `buf` and its length will have been adjusted appropriately.
///
/// [`fill_buf`]: BufRead::fill_buf
///
/// # Examples
///
/// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
/// this example, we use [`Cursor`] to read all the bytes in a byte slice
/// in hyphen delimited segments:
///
/// [`Cursor`]: crate::io::Cursor
///
/// ```
/// use std::io::{self, BufRead};
///
/// let mut cursor = io::Cursor::new(b"lorem-ipsum");
/// let mut buf = vec![];
///
/// // cursor is at 'l'
/// let num_bytes = cursor.read_until(b'-', &mut buf)
/// .expect("reading from cursor won't fail");
/// assert_eq!(num_bytes, 6);
/// assert_eq!(buf, b"lorem-");
/// buf.clear();
///
/// // cursor is at 'i'
/// let num_bytes = cursor.read_until(b'-', &mut buf)
/// .expect("reading from cursor won't fail");
/// assert_eq!(num_bytes, 5);
/// assert_eq!(buf, b"ipsum");
/// buf.clear();
///
/// // cursor is at EOF
/// let num_bytes = cursor.read_until(b'-', &mut buf)
/// .expect("reading from cursor won't fail");
/// assert_eq!(num_bytes, 0);
/// assert_eq!(buf, b"");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize> {
default_read_until(self, byte, buf)
}
/// Skips all bytes until the delimiter `byte` or EOF is reached.
///
/// This function will read (and discard) bytes from the underlying stream until the
/// delimiter or EOF is found.
///
/// If successful, this function will return the total number of bytes read,
/// including the delimiter byte if found.
///
/// This is useful for efficiently skipping data such as NUL-terminated strings
/// in binary file formats without buffering.
///
/// This function is blocking and should be used carefully: it is possible for
/// an attacker to continuously send bytes without ever sending the delimiter
/// or EOF.
///
/// # Errors
///
/// This function will ignore all instances of [`ErrorKind::Interrupted`] and
/// will otherwise return any errors returned by [`fill_buf`].
///
/// If an I/O error is encountered then all bytes read so far will be
/// present in `buf` and its length will have been adjusted appropriately.
///
/// [`fill_buf`]: BufRead::fill_buf
///
/// # Examples
///
/// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
/// this example, we use [`Cursor`] to read some NUL-terminated information
/// about Ferris from a binary string, skipping the fun fact:
///
/// [`Cursor`]: crate::io::Cursor
///
/// ```
/// use std::io::{self, BufRead};
///
/// let mut cursor = io::Cursor::new(b"Ferris\0Likes long walks on the beach\0Crustacean\0!");
///
/// // read name
/// let mut name = Vec::new();
/// let num_bytes = cursor.read_until(b'\0', &mut name)
/// .expect("reading from cursor won't fail");
/// assert_eq!(num_bytes, 7);
/// assert_eq!(name, b"Ferris\0");
///
/// // skip fun fact
/// let num_bytes = cursor.skip_until(b'\0')
/// .expect("reading from cursor won't fail");
/// assert_eq!(num_bytes, 30);
///
/// // read animal type
/// let mut animal = Vec::new();
/// let num_bytes = cursor.read_until(b'\0', &mut animal)
/// .expect("reading from cursor won't fail");
/// assert_eq!(num_bytes, 11);
/// assert_eq!(animal, b"Crustacean\0");
///
/// // reach EOF
/// let num_bytes = cursor.skip_until(b'\0')
/// .expect("reading from cursor won't fail");
/// assert_eq!(num_bytes, 1);
/// ```
#[stable(feature = "bufread_skip_until", since = "1.83.0")]
fn skip_until(&mut self, byte: u8) -> Result<usize> {
default_skip_until(self, byte)
}
/// Reads all bytes until a newline (the `0xA` byte) is reached, and append
/// them to the provided [`String`] buffer.
///
/// Previous content of the buffer will be preserved. To avoid appending to
/// the buffer, you need to [`clear`] it first.
///
/// This function will read bytes from the underlying stream until the
/// newline delimiter (the `0xA` byte) or EOF is found. Once found, all bytes
/// up to, and including, the delimiter (if found) will be appended to
/// `buf`.
///
/// If successful, this function will return the total number of bytes read.
///
/// If this function returns [`Ok(0)`], the stream has reached EOF.
///
/// This function is blocking and should be used carefully: it is possible for
/// an attacker to continuously send bytes without ever sending a newline
/// or EOF. You can use [`take`] to limit the maximum number of bytes read.
///
/// [`Ok(0)`]: Ok
/// [`clear`]: String::clear
/// [`take`]: crate::io::Read::take
///
/// # Errors
///
/// This function has the same error semantics as [`read_until`] and will
/// also return an error if the read bytes are not valid UTF-8. If an I/O
/// error is encountered then `buf` may contain some bytes already read in
/// the event that all data read so far was valid UTF-8.
///
/// [`read_until`]: BufRead::read_until
///
/// # Examples
///
/// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
/// this example, we use [`Cursor`] to read all the lines in a byte slice:
///
/// [`Cursor`]: crate::io::Cursor
///
/// ```
/// use std::io::{self, BufRead};
///
/// let mut cursor = io::Cursor::new(b"foo\nbar");
/// let mut buf = String::new();
///
/// // cursor is at 'f'
/// let num_bytes = cursor.read_line(&mut buf)
/// .expect("reading from cursor won't fail");
/// assert_eq!(num_bytes, 4);
/// assert_eq!(buf, "foo\n");
/// buf.clear();
///
/// // cursor is at 'b'
/// let num_bytes = cursor.read_line(&mut buf)
/// .expect("reading from cursor won't fail");
/// assert_eq!(num_bytes, 3);
/// assert_eq!(buf, "bar");
/// buf.clear();
///
/// // cursor is at EOF
/// let num_bytes = cursor.read_line(&mut buf)
/// .expect("reading from cursor won't fail");
/// assert_eq!(num_bytes, 0);
/// assert_eq!(buf, "");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn read_line(&mut self, buf: &mut String) -> Result<usize> {
// Note that we are not calling the `.read_until` method here, but
// rather our hardcoded implementation. For more details as to why, see
// the comments in `default_read_to_string`.
unsafe { append_to_string(buf, |b| default_read_until(self, b'\n', b)) }
}
/// Returns an iterator over the contents of this reader split on the byte
/// `byte`.
///
/// The iterator returned from this function will return instances of
/// <code>[io::Result]<[Vec]\<u8>></code>. Each vector returned will *not* have
/// the delimiter byte at the end.
///
/// This function will yield errors whenever [`read_until`] would have
/// also yielded an error.
///
/// [io::Result]: self::Result "io::Result"
/// [`read_until`]: BufRead::read_until
///
/// # Examples
///
/// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
/// this example, we use [`Cursor`] to iterate over all hyphen delimited
/// segments in a byte slice
///
/// [`Cursor`]: crate::io::Cursor
///
/// ```
/// use std::io::{self, BufRead};
///
/// let cursor = io::Cursor::new(b"lorem-ipsum-dolor");
///
/// let mut split_iter = cursor.split(b'-').map(|l| l.unwrap());
/// assert_eq!(split_iter.next(), Some(b"lorem".to_vec()));
/// assert_eq!(split_iter.next(), Some(b"ipsum".to_vec()));
/// assert_eq!(split_iter.next(), Some(b"dolor".to_vec()));
/// assert_eq!(split_iter.next(), None);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn split(self, byte: u8) -> Split<Self>
where
Self: Sized,
{
split(self, byte)
}
/// Returns an iterator over the lines of this reader.
///
/// The iterator returned from this function will yield instances of
/// <code>[io::Result]<[String]></code>. Each string returned will *not* have a newline
/// byte (the `0xA` byte) or `CRLF` (`0xD`, `0xA` bytes) at the end.
///
/// [io::Result]: crate::io::Result "io::Result"
///
/// # Examples
///
/// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
/// this example, we use [`Cursor`] to iterate over all the lines in a byte
/// slice.
///
/// [`Cursor`]: crate::io::Cursor
///
/// ```
/// use std::io::{self, BufRead};
///
/// let cursor = io::Cursor::new(b"lorem\nipsum\r\ndolor");
///
/// let mut lines_iter = cursor.lines().map(|l| l.unwrap());
/// assert_eq!(lines_iter.next(), Some(String::from("lorem")));
/// assert_eq!(lines_iter.next(), Some(String::from("ipsum")));
/// assert_eq!(lines_iter.next(), Some(String::from("dolor")));
/// assert_eq!(lines_iter.next(), None);
/// ```
///
/// # Errors
///
/// Each line of the iterator has the same error semantics as [`BufRead::read_line`].
#[stable(feature = "rust1", since = "1.0.0")]
fn lines(self) -> Lines<Self>
where
Self: Sized,
{
lines(self)
}
}
fn default_read_until<R: BufRead + ?Sized>(
r: &mut R,
delim: u8,
buf: &mut Vec<u8>,
) -> Result<usize> {
let mut read = 0;
loop {
let (done, used) = {
let available = match r.fill_buf() {
Ok(n) => n,
Err(ref e) if e.is_interrupted() => continue,
Err(e) => return Err(e),
};
let (done, available) = match memchr::memchr(delim, available) {
Some(i) => (true, &available[..=i]),
None => (false, available),
};
cfg_select! {
no_global_oom_handling => {
let count = available.len();
buf.try_reserve(count)?;
// SAFETY:
// * self and buf are non-overlapping
// * buf[..len] is already initialized
// * buf[len..len + count] is initialized by copy_nonoverlapping
// * len + count is within the capacity of buf based on the reservation completed above
unsafe {
let len = buf.len();
let src = available.as_ptr();
let dst = buf.as_mut_ptr().add(len);
core::ptr::copy_nonoverlapping(src, dst, count);
buf.set_len(len + count);
}
}
_ => {
buf.extend_from_slice(available);
}
}
(done, available.len())
};
r.consume(used);
read += used;
if done || used == 0 {
return Ok(read);
}
}
}
fn default_skip_until<R: BufRead + ?Sized>(r: &mut R, delim: u8) -> Result<usize> {
let mut read = 0;
loop {
let (done, used) = {
let available = match r.fill_buf() {
Ok(n) => n,
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
};
match memchr::memchr(delim, available) {
Some(i) => (true, i + 1),
None => (false, available.len()),
}
};
r.consume(used);
read += used;
if done || used == 0 {
return Ok(read);
}
}
}