mod buf_read_backer;
mod impls;
pub use buf_read_backer::BufReadBacker;
use std::{
cmp,
io::{self, ErrorKind, IoSliceMut, Result},
slice,
};
use crate::DEFAULT_BUF_SIZE;
pub trait ReadBack {
fn read_back(&mut self, buf: &mut [u8]) -> Result<usize>;
fn read_back_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> {
default_read_back_vectored(|b| self.read_back(b), bufs)
}
fn read_back_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
default_read_back_to_end(self, buf)
}
fn read_back_to_string(&mut self, buf: &mut String) -> Result<usize> {
default_read_back_to_string(self, buf)
}
fn read_back_exact(&mut self, buf: &mut [u8]) -> Result<()> {
default_read_back_exact(self, buf)
}
fn read_back_bytes(self) -> ReadBackBytes<Self>
where
Self: Sized,
{
ReadBackBytes { inner: self }
}
fn read_back_chain<R: ReadBack>(self, next: R) -> ReadBackChain<Self, R>
where
Self: Sized,
{
ReadBackChain {
first: self,
second: next,
done_first: false,
}
}
fn read_back_take(self, limit: u64) -> ReadBackTake<Self>
where
Self: Sized,
{
ReadBackTake { inner: self, limit }
}
}
pub trait BufReadBack: ReadBack {
fn read_back_fill_buf(&mut self) -> io::Result<&[u8]>;
fn read_back_consume(&mut self, amt: usize);
fn read_back_has_data_left(&mut self) -> io::Result<bool> {
self.read_back_fill_buf().map(|buffer| buffer.is_empty())
}
fn read_back_until(&mut self, delim: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
default_buf_read_back_until(self, delim, buf)
}
fn read_back_skip_until(&mut self, delim: u8) -> io::Result<usize> {
default_buf_read_skip_until(self, delim)
}
fn read_back_line(&mut self, dest: &mut String) -> io::Result<usize> {
default_buf_read_back_line(self, dest)
}
fn read_back_split(self, delim: u8) -> ReadBackSplit<Self>
where
Self: Sized,
{
ReadBackSplit { buf: self, delim }
}
fn read_back_lines(self) -> ReadBackLines<Self>
where
Self: Sized,
{
ReadBackLines { buf: self }
}
}
#[derive(Debug)]
pub struct ReadBackBytes<R> {
inner: R,
}
impl<R: ReadBack> Iterator for ReadBackBytes<R> {
type Item = Result<u8>;
fn next(&mut self) -> Option<Result<u8>> {
let mut byte: u8 = 0;
loop {
return match self.inner.read_back(slice::from_mut(&mut byte)) {
Ok(0) => None,
Err(e) if e.kind() == ErrorKind::Other => None,
Ok(..) => Some(Ok(byte)),
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => Some(Err(e)),
};
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
#[derive(Debug)]
pub struct ReadBackChain<T, U> {
first: T,
second: U,
done_first: bool,
}
impl<T, U> ReadBackChain<T, U> {
pub fn into_inner(self) -> (T, U) {
(self.first, self.second)
}
pub fn get_ref(&self) -> (&T, &U) {
(&self.first, &self.second)
}
pub fn get_mut(&mut self) -> (&mut T, &mut U) {
(&mut self.first, &mut self.second)
}
}
impl<T: ReadBack, U: ReadBack> ReadBack for ReadBackChain<T, U> {
fn read_back(&mut self, buf: &mut [u8]) -> Result<usize> {
if !self.done_first {
match self.first.read_back(buf)? {
0 if !buf.is_empty() => self.done_first = true,
n => return Ok(n),
}
}
self.second.read_back(buf)
}
fn read_back_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> {
if !self.done_first {
match self.first.read_back_vectored(bufs)? {
0 if bufs.iter().any(|b| !b.is_empty()) => self.done_first = true,
n => return Ok(n),
}
}
self.second.read_back_vectored(bufs)
}
fn read_back_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
let mut read = 0;
if !self.done_first {
read += self.first.read_back_to_end(buf)?;
self.done_first = true;
}
read += self.second.read_back_to_end(buf)?;
Ok(read)
}
}
impl<T: BufReadBack, U: BufReadBack> BufReadBack for ReadBackChain<T, U> {
fn read_back_fill_buf(&mut self) -> Result<&[u8]> {
if !self.done_first {
match self.first.read_back_fill_buf()? {
[] => self.done_first = true,
buf => return Ok(buf),
}
}
self.second.read_back_fill_buf()
}
fn read_back_consume(&mut self, amt: usize) {
if !self.done_first {
self.first.read_back_consume(amt)
} else {
self.second.read_back_consume(amt)
}
}
fn read_back_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize> {
let mut read = 0;
if !self.done_first {
let n = self.first.read_back_until(byte, buf)?;
read += n;
match buf.last() {
Some(b) if *b == byte && n != 0 => return Ok(read),
_ => self.done_first = true,
}
}
read += self.second.read_back_until(byte, buf)?;
Ok(read)
}
}
#[derive(Debug)]
pub struct ReadBackSplit<B> {
buf: B,
delim: u8,
}
impl<B: BufReadBack> Iterator for ReadBackSplit<B> {
type Item = Result<Vec<u8>>;
fn next(&mut self) -> Option<Result<Vec<u8>>> {
let mut buf = Vec::new();
match self.buf.read_back_until(self.delim, &mut buf) {
Ok(0) => None,
Ok(_n) => {
if buf[0] == self.delim {
buf.drain(..1);
}
Some(Ok(buf))
}
Err(e) => Some(Err(e)),
}
}
}
#[derive(Debug)]
pub struct ReadBackLines<B> {
buf: B,
}
impl<B: BufReadBack> Iterator for ReadBackLines<B> {
type Item = Result<String>;
fn next(&mut self) -> Option<Result<String>> {
let mut buf = String::new();
match self.buf.read_back_line(&mut buf) {
Ok(0) => None,
Ok(_n) => {
if buf.starts_with('\n') {
buf = buf.drain(1..).collect();
} else if buf.starts_with("\r\n") {
buf = buf.drain(2..).collect();
}
Some(Ok(buf))
}
Err(e) => Some(Err(e)),
}
}
}
#[derive(Debug)]
pub struct ReadBackTake<T> {
inner: T,
limit: u64,
}
impl<T> ReadBackTake<T> {
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: ReadBack> ReadBack for ReadBackTake<T> {
fn read_back(&mut self, buf: &mut [u8]) -> Result<usize> {
if self.limit == 0 {
return Ok(0);
}
let max = cmp::min(buf.len() as u64, self.limit) as usize;
let n = self.inner.read_back(&mut buf[..max])?;
assert!(n as u64 <= self.limit, "number of read bytes exceeds limit");
self.limit -= n as u64;
Ok(n)
}
}
impl<T: BufReadBack> BufReadBack for ReadBackTake<T> {
fn read_back_fill_buf(&mut self) -> Result<&[u8]> {
if self.limit == 0 {
return Ok(&[]);
}
let buf = self.inner.read_back_fill_buf()?;
let buf_len = buf.len();
let cap = cmp::min(buf_len as u64, self.limit) as usize;
Ok(&buf[buf_len - cap..])
}
fn read_back_consume(&mut self, amt: usize) {
let amt = cmp::min(amt as u64, self.limit) as usize;
self.limit -= amt as u64;
self.inner.read_back_consume(amt);
}
}
pub fn default_read_back_vectored<F: FnOnce(&mut [u8]) -> Result<usize>>(
read_back: F,
bufs: &mut [IoSliceMut<'_>],
) -> Result<usize> {
let buf = bufs
.iter_mut()
.find(|b| !b.is_empty())
.map_or(&mut [][..], |b| &mut **b);
read_back(buf)
}
pub fn default_read_back_to_end<R: ReadBack + ?Sized>(
reader: &mut R,
dest_buf: &mut Vec<u8>,
) -> Result<usize> {
let mut buffers: Vec<Vec<u8>> = vec![];
let mut curr_buffer: Vec<u8> = vec![0; DEFAULT_BUF_SIZE];
let mut amount_read: usize = 0;
loop {
match reader.read_back(curr_buffer.as_mut_slice()) {
Ok(amount) => {
println!("{}", amount);
if amount == 0 {
let mut final_buf = Vec::with_capacity(amount_read + dest_buf.len());
for buffer in buffers.into_iter().rev() {
final_buf.extend_from_slice(&buffer);
}
final_buf.extend_from_slice(dest_buf);
*dest_buf = final_buf;
return Ok(amount_read);
}
curr_buffer = {
let curr_buffer_len = curr_buffer.len();
curr_buffer[curr_buffer_len - amount..].to_vec()
};
amount_read += amount;
buffers.push(curr_buffer);
curr_buffer = Vec::new();
}
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
}
}
}
fn default_read_back_to_string<R: ReadBack + ?Sized>(r: &mut R, buf: &mut String) -> Result<usize> {
let mut bytes_buf = Vec::new();
let amount_bytes = default_read_back_to_end(r, &mut bytes_buf)?;
let mut read_back_string = String::from_utf8(bytes_buf).map_err(|e| {
std::io::Error::new(
ErrorKind::InvalidData,
format!("Couldn't convert the read-back content to a string: {}", e),
)
})?;
read_back_string.push_str(buf);
*buf = read_back_string;
Ok(amount_bytes)
}
fn default_read_back_exact<R: ReadBack + ?Sized>(r: &mut R, mut buf: &mut [u8]) -> Result<()> {
while !buf.is_empty() {
match r.read_back(buf) {
Ok(0) => break,
Ok(n) => {
let buf_len = buf.len();
buf = &mut buf[..buf_len - n];
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
if !buf.is_empty() {
Err(std::io::Error::new(
ErrorKind::UnexpectedEof,
"Failed to fill whole buffer.",
))
} else {
Ok(())
}
}
fn default_buf_read_back_until<R: BufReadBack + ?Sized>(
r: &mut R,
delim: u8,
buf: &mut Vec<u8>,
) -> io::Result<usize> {
let mut amount_read = 0;
loop {
let (done, used) = {
let new_read = match r.read_back_fill_buf() {
Ok(n) => n,
Err(err) if err.kind() == ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
};
match memchr::memrchr(delim, new_read) {
Some(index) => {
let used = new_read.len() - index;
let mut new_buf = Vec::with_capacity(buf.len() + used);
new_buf.extend_from_slice(&new_read[index..]);
new_buf.extend_from_slice(buf);
*buf = new_buf;
(true, used)
}
None => {
let mut new_buf = Vec::with_capacity(buf.len() + new_read.len());
new_buf.extend_from_slice(new_read);
new_buf.extend_from_slice(buf);
*buf = new_buf;
(false, new_read.len())
}
}
};
r.read_back_consume(used);
amount_read += used;
if done || used == 0 {
return Ok(amount_read);
}
}
}
fn default_buf_read_skip_until<R: BufReadBack + ?Sized>(r: &mut R, delim: u8) -> Result<usize> {
let mut amount_read: usize = 0;
loop {
let (done, used) = {
let new_read = match r.read_back_fill_buf() {
Ok(n) => n,
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
};
match memchr::memrchr(delim, new_read) {
Some(index) => (true, new_read.len() - index),
None => (false, new_read.len()),
}
};
r.read_back_consume(used);
amount_read += used;
if done || used == 0 {
return Ok(amount_read);
}
}
}
fn default_buf_read_back_line<R: BufReadBack + ?Sized>(
r: &mut R,
dest: &mut String,
) -> io::Result<usize> {
let mut buffer = Vec::with_capacity(crate::DEFAULT_BUF_SIZE);
let mut amount_read = r.read_back_until(b'\n', &mut buffer)?;
if r.read_back_fill_buf()?
.last()
.map(|&c| c == b'\r')
.unwrap_or(false)
{
let mut new_buf = Vec::with_capacity(buffer.len() + 1);
new_buf.push(b'\r');
new_buf.extend_from_slice(&buffer);
buffer = new_buf;
amount_read += 1;
r.read_back_consume(1);
}
match String::from_utf8(buffer) {
Ok(mut line) => {
line.push_str(dest);
*dest = line;
Ok(amount_read)
}
Err(err) => Err(io::Error::new(ErrorKind::InvalidData, err)),
}
}