#[cfg(feature = "alloc")]
use alloc::{string::String, vec::Vec};
use core::io::BorrowedCursor;
use crate::{Chain, Error, Result, Take};
mod impls;
pub fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [u8]) -> Result<()> {
while !buf.is_empty() {
match this.read(buf) {
Ok(0) => break,
Ok(n) => {
buf = &mut buf[n..];
}
Err(e) if e.canonicalize() == Error::Interrupted => continue,
Err(e) => return Err(e),
}
}
if !buf.is_empty() {
Err(Error::UnexpectedEof)
} else {
Ok(())
}
}
pub fn default_read_buf<F>(read: F, mut cursor: BorrowedCursor<'_, u8>) -> Result<()>
where
F: FnOnce(&mut [u8]) -> Result<usize>,
{
let n = read(cursor.ensure_init())?;
cursor.advance_checked(n);
Ok(())
}
pub fn default_read_buf_exact<R: Read + ?Sized>(
this: &mut R,
mut cursor: BorrowedCursor<'_, u8>,
) -> Result<()> {
while cursor.capacity() > 0 {
let prev_written = cursor.written();
match this.read_buf(cursor.reborrow()) {
Ok(()) => {}
Err(e) if e.canonicalize() == Error::Interrupted => continue,
Err(e) => return Err(e),
}
if cursor.written() == prev_written {
return Err(Error::UnexpectedEof);
}
}
Ok(())
}
#[cfg(feature = "alloc")]
pub fn default_read_to_end<R: Read + ?Sized>(
r: &mut R,
buf: &mut Vec<u8>,
size_hint: Option<usize>,
) -> Result<usize> {
use core::io::BorrowedBuf;
use crate::DEFAULT_BUF_SIZE;
let start_len = buf.len();
let start_cap = buf.capacity();
let mut max_read_size = size_hint
.and_then(|s| {
s.checked_add(1024)?
.checked_next_multiple_of(DEFAULT_BUF_SIZE)
})
.unwrap_or(DEFAULT_BUF_SIZE);
const PROBE_SIZE: usize = 32;
fn small_probe_read<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
let mut probe = [0u8; PROBE_SIZE];
loop {
match r.read(&mut probe) {
Ok(n) => {
buf.extend_from_slice(&probe[..n]);
return Ok(n);
}
Err(e) if e.canonicalize() == Error::Interrupted => continue,
Err(e) => return Err(e),
}
}
}
if (size_hint.is_none() || size_hint == Some(0)) && buf.capacity() - buf.len() < PROBE_SIZE {
let read = small_probe_read(r, buf)?;
if read == 0 {
return Ok(0);
}
}
loop {
if buf.len() == buf.capacity() && buf.capacity() == start_cap {
let read = small_probe_read(r, buf)?;
if read == 0 {
return Ok(buf.len() - start_len);
}
}
if buf.len() == buf.capacity() {
buf.try_reserve(PROBE_SIZE).map_err(|_| Error::NoMemory)?;
}
let mut spare = buf.spare_capacity_mut();
let buf_len = spare.len().min(max_read_size);
spare = &mut spare[..buf_len];
let mut read_buf: BorrowedBuf<'_, u8> = spare.into();
let mut cursor = read_buf.unfilled();
let result = loop {
match r.read_buf(cursor.reborrow()) {
Err(e) if e.canonicalize() == Error::Interrupted => continue,
res => break res,
}
};
let bytes_read = cursor.written();
let is_init = read_buf.is_init();
unsafe {
let new_len = bytes_read + buf.len();
buf.set_len(new_len);
}
result?;
if bytes_read == 0 {
return Ok(buf.len() - start_len);
}
if size_hint.is_none() {
if !is_init {
max_read_size = usize::MAX;
}
else if buf_len >= max_read_size && bytes_read == buf_len {
max_read_size = max_read_size.saturating_mul(2);
}
}
}
}
#[cfg(feature = "alloc")]
pub(crate) unsafe fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
where
F: FnOnce(&mut Vec<u8>) -> Result<usize>,
{
struct Guard<'a> {
buf: &'a mut Vec<u8>,
len: usize,
}
impl Drop for Guard<'_> {
fn drop(&mut self) {
unsafe {
self.buf.set_len(self.len);
}
}
}
let mut g = Guard {
len: buf.len(),
buf: unsafe { buf.as_mut_vec() },
};
let ret = f(g.buf);
let appended = unsafe { g.buf.get_unchecked(g.len..) };
if str::from_utf8(appended).is_err() {
ret.and(Err(Error::IllegalBytes))
} else {
g.len = g.buf.len();
ret
}
}
#[cfg(feature = "alloc")]
pub fn default_read_to_string<R: Read + ?Sized>(
r: &mut R,
buf: &mut String,
size_hint: Option<usize>,
) -> Result<usize> {
unsafe { append_to_string(buf, |b| default_read_to_end(r, b, size_hint)) }
}
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
default_read_exact(self, buf)
}
fn read_buf(&mut self, buf: BorrowedCursor<'_, u8>) -> Result<()> {
default_read_buf(|b| self.read(b), buf)
}
fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_, u8>) -> Result<()> {
default_read_buf_exact(self, cursor)
}
#[cfg(feature = "alloc")]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
default_read_to_end(self, buf, None)
}
#[cfg(feature = "alloc")]
fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
default_read_to_string(self, buf, None)
}
fn by_ref(&mut self) -> &mut Self
where
Self: Sized,
{
self
}
fn chain<R: Read>(self, next: R) -> Chain<Self, R>
where
Self: Sized,
{
Chain::new(self, next)
}
fn take(self, limit: u64) -> Take<Self>
where
Self: Sized,
{
Take::new(self, limit)
}
}
#[cfg(feature = "alloc")]
pub fn read_to_string<R: Read>(mut reader: R) -> Result<String> {
let mut buf = String::new();
reader.read_to_string(&mut buf)?;
Ok(buf)
}
pub trait BufRead: Read {
fn fill_buf(&mut self) -> Result<&[u8]>;
fn consume(&mut self, amount: usize);
fn has_data_left(&mut self) -> Result<bool> {
self.fill_buf().map(|b| !b.is_empty())
}
fn skip_until(&mut self, byte: u8) -> Result<usize> {
let mut read = 0;
loop {
let (done, used) = {
let available = self.fill_buf()?;
match memchr::memchr(byte, available) {
Some(i) => (true, i + 1),
None => (false, available.len()),
}
};
self.consume(used);
read += used;
if done || used == 0 {
return Ok(read);
}
}
}
#[cfg(feature = "alloc")]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize> {
let mut read = 0;
loop {
let (done, used) = {
let available = self.fill_buf()?;
match memchr::memchr(byte, available) {
Some(i) => {
buf.extend_from_slice(&available[..=i]);
(true, i + 1)
}
None => {
buf.extend_from_slice(available);
(false, available.len())
}
}
};
self.consume(used);
read += used;
if done || used == 0 {
return Ok(read);
}
}
}
#[cfg(feature = "alloc")]
fn read_line(&mut self, buf: &mut String) -> Result<usize> {
unsafe { super::append_to_string(buf, |b| self.read_until(b'\n', b)) }
}
#[cfg(feature = "alloc")]
fn split(self, byte: u8) -> Split<Self>
where
Self: Sized,
{
Split {
buf: self,
delim: byte,
}
}
#[cfg(feature = "alloc")]
fn lines(self) -> Lines<Self>
where
Self: Sized,
{
Lines { buf: self }
}
}
#[cfg(feature = "alloc")]
#[derive(Debug)]
pub struct Split<B> {
buf: B,
delim: u8,
}
#[cfg(feature = "alloc")]
impl<B: BufRead> Iterator for Split<B> {
type Item = Result<Vec<u8>>;
fn next(&mut self) -> Option<Result<Vec<u8>>> {
let mut buf = Vec::new();
match self.buf.read_until(self.delim, &mut buf) {
Ok(0) => None,
Ok(_n) => {
if buf[buf.len() - 1] == self.delim {
buf.pop();
}
Some(Ok(buf))
}
Err(e) => Some(Err(e)),
}
}
}
#[cfg(feature = "alloc")]
#[derive(Debug)]
pub struct Lines<B> {
buf: B,
}
#[cfg(feature = "alloc")]
impl<B: BufRead> Iterator for Lines<B> {
type Item = Result<String>;
fn next(&mut self) -> Option<Result<String>> {
let mut buf = String::new();
match self.buf.read_line(&mut buf) {
Ok(0) => None,
Ok(_n) => {
if buf.ends_with('\n') {
buf.pop();
if buf.ends_with('\r') {
buf.pop();
}
}
Some(Ok(buf))
}
Err(e) => Some(Err(e)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn read_default_read_exact_with_interrupt_hold() {
use crate::{Error, Read, default_read_exact};
struct InterruptReader {
calls: usize,
}
impl Read for InterruptReader {
fn read(&mut self, buf: &mut [u8]) -> crate::Result<usize> {
self.calls += 1;
if self.calls <= 2 {
return Err(Error::Interrupted);
}
buf[0] = 42;
Ok(1)
}
}
let mut reader = InterruptReader { calls: 0 };
let mut buf = [0u8; 1];
let result = default_read_exact(&mut reader, &mut buf);
assert!(result.is_ok());
assert_eq!(buf[0], 42);
}
#[test]
fn read_take_struct_and_methods_hold() {
use crate::{Read, Take};
struct ExactReader;
impl Read for ExactReader {
fn read(&mut self, buf: &mut [u8]) -> crate::Result<usize> {
for byte in buf.iter_mut() {
*byte = 0xAB;
}
Ok(buf.len())
}
}
let reader = ExactReader;
let mut take = Take::new(reader, 5);
assert_eq!(take.limit(), 5);
let mut buf = [0u8; 3];
let n = take.read(&mut buf).unwrap();
assert_eq!(n, 3);
assert_eq!(take.limit(), 2);
}
#[test]
fn read_default_read_exact_eof_hold() {
use crate::Read;
struct EofReader;
impl Read for EofReader {
fn read(&mut self, _buf: &mut [u8]) -> crate::Result<usize> {
Ok(0)
}
}
let mut reader = EofReader;
let mut buf = [0u8; 10];
let result = default_read_exact(&mut reader, &mut buf);
assert!(result.is_err());
}
#[test]
fn read_by_ref_and_chain_hold() {
use crate::{Chain, Read};
struct FirstReader {
data: [u8; 4],
pos: usize,
}
impl Read for FirstReader {
fn read(&mut self, buf: &mut [u8]) -> crate::Result<usize> {
let remaining = self.data.len() - self.pos;
let to_copy = remaining.min(buf.len());
if to_copy == 0 {
return Ok(0);
}
buf[..to_copy].copy_from_slice(&self.data[self.pos..self.pos + to_copy]);
self.pos += to_copy;
Ok(to_copy)
}
}
struct SecondReader {
data: [u8; 3],
pos: usize,
}
impl Read for SecondReader {
fn read(&mut self, buf: &mut [u8]) -> crate::Result<usize> {
let remaining = self.data.len() - self.pos;
let to_copy = remaining.min(buf.len());
if to_copy == 0 {
return Ok(0);
}
buf[..to_copy].copy_from_slice(&self.data[self.pos..self.pos + to_copy]);
self.pos += to_copy;
Ok(to_copy)
}
}
let mut first = FirstReader {
data: [1, 2, 3, 4],
pos: 0,
};
let _ref = first.by_ref();
let mut buf = [0u8; 2];
let n = first.read(&mut buf).unwrap();
assert_eq!(n, 2);
assert_eq!(buf[0], 1);
assert_eq!(buf[1], 2);
let first = FirstReader {
data: [1, 2, 3, 4],
pos: 0,
};
let second = SecondReader {
data: [5, 6, 7],
pos: 0,
};
let mut chained = Chain::new(first, second);
let mut buf = [0u8; 10];
let n1 = chained.read(&mut buf).unwrap();
assert_eq!(n1, 4);
let n2 = chained.read(&mut buf[4..]).unwrap();
assert_eq!(n2, 3);
assert_eq!(buf[..7], [1, 2, 3, 4, 5, 6, 7]);
}
#[test]
fn read_take_exhaustion_and_limit_hold() {
use crate::{Read, Take};
struct FixedReader {
data: [u8; 10],
pos: usize,
}
impl Read for FixedReader {
fn read(&mut self, buf: &mut [u8]) -> crate::Result<usize> {
let remaining = self.data.len() - self.pos;
let to_copy = remaining.min(buf.len());
if to_copy == 0 {
return Ok(0);
}
buf[..to_copy].copy_from_slice(&self.data[self.pos..self.pos + to_copy]);
self.pos += to_copy;
Ok(to_copy)
}
}
let reader = FixedReader {
data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
pos: 0,
};
let mut take = Take::new(reader, 3);
let mut buf = [0u8; 5];
let n = take.read(&mut buf).unwrap();
assert_eq!(n, 3);
assert_eq!(take.limit(), 0);
assert_eq!(buf[..3], [0, 1, 2]);
let n2 = take.read(&mut buf).unwrap();
assert_eq!(n2, 0);
}
#[test]
fn read_bufread_has_data_left_and_skip_until_hold() {
use crate::{BufRead, Read};
struct BufferedReader {
data: [u8; 6],
pos: usize,
}
impl Read for BufferedReader {
fn read(&mut self, buf: &mut [u8]) -> crate::Result<usize> {
let remaining = self.data.len() - self.pos;
let to_copy = remaining.min(buf.len());
if to_copy == 0 {
return Ok(0);
}
buf[..to_copy].copy_from_slice(&self.data[self.pos..self.pos + to_copy]);
self.pos += to_copy;
Ok(to_copy)
}
}
impl BufRead for BufferedReader {
fn fill_buf(&mut self) -> crate::Result<&[u8]> {
if self.pos < self.data.len() {
Ok(&self.data[self.pos..])
} else {
Ok(&[])
}
}
fn consume(&mut self, amount: usize) {
self.pos += amount;
}
}
let mut reader = BufferedReader {
data: [1, 2, 3, 4, 5, 6],
pos: 0,
};
assert!(reader.has_data_left().unwrap());
reader.consume(6);
assert!(!reader.has_data_left().unwrap());
let mut reader2 = BufferedReader {
data: [1, 2, 0xFF, 4, 5, 6],
pos: 0,
};
let skipped = reader2.skip_until(0xFF).unwrap();
assert_eq!(skipped, 3); }
}