#[cfg(feature = "alloc")]
use crate::Vec;
use crate::{IoError, IoErrorKind, IoResult, OptRes, Slice, is, sf};
use ::core::{cmp, fmt};
#[doc = crate::_tags!(io)]
#[rustfmt::skip]
pub trait IoRead {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize>;
#[cfg(feature = "alloc")]
#[cfg_attr(nightly_doc, doc(cfg(feature = "alloc")))]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> IoResult<usize> {
alloc_impls::read_to_end(self, buf)
}
fn read_exact(&mut self, mut buf: &mut [u8]) -> IoResult<()> {
while !buf.is_empty() {
match self.read(buf) {
Ok(0) => break,
Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; }
Err(ref e) if e.kind() == IoErrorKind::Interrupted => {}
Err(e) => return Err(e),
} }
if !buf.is_empty() {
Err(IoError::new(IoErrorKind::UnexpectedEof, "failed to fill whole buffer"))
} else { Ok(()) }
}
fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
fn bytes(self) -> IoBytes<Self> where Self: Sized { IoBytes { inner: self } }
fn chain<R: IoRead>(self, next: R) -> IoChain<Self, R> where Self: Sized {
IoChain::new(self, next, false) }
fn take(self, limit: u64) -> IoTake<Self> where Self: Sized { IoTake::new(self, limit) }
}
pub trait IoBufRead: IoRead {
fn fill_buf(&mut self) -> IoResult<&[u8]>;
fn consume(&mut self, amt: usize);
}
#[derive(Debug)]
pub struct IoBytes<R> {
pub(super) inner: R,
}
impl<R: IoRead> Iterator for IoBytes<R> {
type Item = IoResult<u8>;
fn next(&mut self) -> OptRes<u8, IoError> {
let mut byte = 0;
loop {
return match self.inner.read(Slice::from_mut(&mut byte)) {
Ok(0) => None,
Ok(..) => Some(Ok(byte)),
Err(ref e) if e.kind() == IoErrorKind::Interrupted => continue,
Err(e) => Some(Err(e)),
};
}
}
}
pub struct IoChain<T, U> {
first: T,
second: U,
done_first: bool,
}
#[rustfmt::skip]
impl<T, U> IoChain<T, U> {
pub(super) const fn new(first: T, second: U, done_first: bool) -> Self {
IoChain { first, second, done_first }
}
pub fn into_inner(self) -> (T, U) { (self.first, self.second) }
pub const fn get_ref(&self) -> (&T, &U) { (&self.first, &self.second) }
pub const fn get_mut(&mut self) -> (&mut T, &mut U) { (&mut self.first, &mut self.second) }
}
impl<T: fmt::Debug, U: fmt::Debug> fmt::Debug for IoChain<T, U> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("IoChain").field("t", &self.first).field("u", &self.second).finish()
}
}
impl<T: IoRead, U: IoRead> IoRead for IoChain<T, U> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
if !self.done_first {
match self.first.read(buf)? {
0 if !buf.is_empty() => self.done_first = true,
n => return Ok(n),
}
}
self.second.read(buf)
}
}
impl<T: IoBufRead, U: IoBufRead> IoBufRead for IoChain<T, U> {
fn fill_buf(&mut self) -> IoResult<&[u8]> {
if !self.done_first {
match self.first.fill_buf()? {
[] => {
self.done_first = true;
}
buf => return Ok(buf),
}
}
self.second.fill_buf()
}
fn consume(&mut self, amt: usize) {
is![!self.done_first, self.first.consume(amt), self.second.consume(amt)];
}
}
#[derive(Debug)]
pub struct IoTake<T> {
inner: T,
limit: u64,
}
#[rustfmt::skip]
impl<T> IoTake<T> {
pub(super) fn new(inner: T, limit: u64) -> Self { IoTake { inner, limit } }
pub fn limit(&self) -> u64 { self.limit }
pub fn set_limit(&mut self, limit: u64) { self.limit = limit; }
pub fn into_inner(self) -> T { self.inner }
pub fn get_ref(&self) -> &T { &self.inner }
pub fn get_mut(&mut self) -> &mut T { &mut self.inner }
}
impl<T: IoRead> IoRead for IoTake<T> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
is![self.limit == 0, return Ok(0)];
let max = cmp::min(buf.len() as u64, self.limit) as usize;
let n = self.inner.read(&mut buf[..max])?;
self.limit -= n as u64;
Ok(n)
}
#[cfg(feature = "alloc")]
#[cfg_attr(nightly_doc, doc(cfg(feature = "alloc")))]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> IoResult<usize> {
alloc_impls::read_to_end_with_reservation(self, buf, |self_| {
cmp::min(self_.limit, 32) as usize
})
}
}
impl<T: IoBufRead> IoBufRead for IoTake<T> {
fn fill_buf(&mut self) -> IoResult<&[u8]> {
is![self.limit == 0, return Ok(&[])];
let buf = self.inner.fill_buf()?;
let cap = cmp::min(buf.len() as u64, self.limit) as usize;
Ok(&buf[..cap])
}
fn consume(&mut self, amt: usize) {
let amt = cmp::min(amt as u64, self.limit) as usize;
self.limit -= amt as u64;
self.inner.consume(amt);
}
}
sf! {
impl<R: IoRead + ?Sized> IoRead for &mut R {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> { (**self).read(buf) }
fn read_exact(&mut self, buf: &mut [u8]) -> IoResult<()> { (**self).read_exact(buf) }
}
impl<B: IoBufRead + ?Sized> IoBufRead for &mut B {
fn fill_buf(&mut self) -> IoResult<&[u8]> { (**self).fill_buf() }
fn consume(&mut self, amt: usize) { (**self).consume(amt); }
}
}
impl IoRead for &[u8] {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
let amt = cmp::min(buf.len(), self.len());
let (a, b) = self.split_at(amt);
is![amt == 1, buf[0] = a[0], buf[..amt].copy_from_slice(a)];
*self = b;
Ok(amt)
}
fn read_exact(&mut self, buf: &mut [u8]) -> IoResult<()> {
if buf.len() > self.len() {
return Err(IoError::new(IoErrorKind::UnexpectedEof, "failed to fill whole buffer"));
}
let (a, b) = self.split_at(buf.len());
is![buf.len() == 1, buf[0] = a[0], buf.copy_from_slice(a)];
*self = b;
Ok(())
}
}
#[rustfmt::skip]
impl IoBufRead for &[u8] {
fn fill_buf(&mut self) -> IoResult<&[u8]> { Ok(*self) }
fn consume(&mut self, amt: usize) { *self = &self[amt..]; }
}
#[cfg(feature = "alloc")]
mod alloc_impls {
use super::*;
pub(super) fn read_to_end<R: IoRead + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> IoResult<usize> {
read_to_end_with_reservation(r, buf, |_| 32)
}
#[cfg(any(feature = "safe_sys", not(feature = "unsafe_slice")))]
pub(super) fn read_to_end_with_reservation<R, F>(
r: &mut R,
buf: &mut Vec<u8>,
mut reservation_size: F,
) -> IoResult<usize>
where
R: IoRead + ?Sized,
F: FnMut(&R) -> usize,
{
const PROBE_SIZE: usize = 32;
fn small_probe_read<R: IoRead + ?Sized>(
r: &mut R,
buf: &mut Vec<u8>,
probe_size: usize,
) -> IoResult<usize> {
let mut probe = crate::vec_![0u8; probe_size];
match r.read(&mut probe) {
Ok(n) => {
probe.truncate(n);
buf.extend_from_slice(&probe);
Ok(n)
}
Err(ref e) if e.kind() == IoErrorKind::Interrupted => Ok(0),
Err(e) => Err(e),
}
}
let start_len = buf.len();
if (reservation_size(r) == 0 || buf.capacity() == buf.len())
&& buf.capacity() - buf.len() < PROBE_SIZE
{
let read = small_probe_read(r, buf, PROBE_SIZE)?;
is![read == 0, return Ok(0)];
}
loop {
if buf.len() == buf.capacity() {
buf.reserve(cmp::min(reservation_size(r), PROBE_SIZE));
}
let buf_len = buf.len(); buf.resize(buf.capacity(), 0); let read_result = {
let spare = &mut buf[buf_len..];
r.read(spare)
};
match read_result {
Ok(0) => {
buf.truncate(buf_len); return Ok(buf_len - start_len);
}
Ok(read_bytes) => {
buf.truncate(buf_len + read_bytes); }
Err(e) => {
buf.truncate(buf_len); return Err(e);
}
}
}
}
#[cfg(all(not(feature = "safe_sys"), feature = "unsafe_slice"))]
pub(super) fn read_to_end_with_reservation<R, F>(
r: &mut R,
buf: &mut Vec<u8>,
mut reservation_size: F,
) -> IoResult<usize>
where
R: IoRead + ?Sized,
F: FnMut(&R) -> usize,
{
const PROBE_SIZE: usize = 32;
fn small_probe_read<R: IoRead + ?Sized>(
r: &mut R,
buf: &mut Vec<u8>,
_probe_size: usize,
) -> IoResult<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(ref e) if e.kind() == IoErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
}
let start_len = buf.len();
if (reservation_size(r) == 0 || buf.capacity() == buf.len())
&& buf.capacity() - buf.len() < PROBE_SIZE
{
let read = small_probe_read(r, buf, PROBE_SIZE)?;
is![read == 0, return Ok(0)];
}
loop {
if buf.len() == buf.capacity() {
buf.reserve(cmp::min(reservation_size(r), PROBE_SIZE));
}
let buf_len = buf.len();
sf! { unsafe { buf.set_len(buf.capacity()); }}
let read_result = {
let spare = &mut buf[buf_len..];
r.read(spare)
};
match read_result {
Ok(0) => {
sf! { unsafe { buf.set_len(buf_len); }}
return Ok(buf_len - start_len);
}
Ok(read_bytes) => sf! { unsafe { buf.set_len(buf_len + read_bytes); }},
Err(e) => {
sf! { unsafe { buf.set_len(buf_len); }}
return Err(e);
}
}
if buf.len() < buf.capacity() {
continue;
}
}
}
}