use std::io::{self, Read, Write};
use crate::buf::Buf;
use super::cdr::CdrSender;
const RECV_MIN_LEN: usize = 512;
const SENDER_DROP_OF_THRESHOLD: usize = 1 * 1024;
pub trait ReadExt: Read {
fn read_nb_to_cdr(&mut self, buf: &mut Buf<u8, 1>) -> io::Result<(usize, bool)> {
let buffer = buf.make_mut();
let mut total_len = 0;
loop {
let at = buffer.len();
if buffer.capacity() < RECV_MIN_LEN {
buffer.reserve(RECV_MIN_LEN);
} else {
buffer.reserve(1);
}
let capacity = buffer.capacity();
buffer.set_len(capacity);
let read = match self.read(&mut buffer.as_mut_slice()[at..]) {
Ok(0) => {
buffer.set_len(at);
return Ok((total_len, true));
}
Ok(read) => read,
Err(err) if err.kind() == io::ErrorKind::Interrupted => {
buffer.set_len(at);
continue;
}
Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
buffer.set_len(at);
return Ok((total_len, false));
}
Err(err) => {
buffer.set_len(at);
return Err(err);
}
};
total_len += read;
buffer.set_len(at + read);
}
}
}
pub trait WriteExt: Write {
fn write_nb_from_cdr(&mut self, sender: &mut CdrSender) -> io::Result<()> {
loop {
let buffer = sender.buffer();
if buffer.is_empty() {
break;
}
match self.write(buffer) {
Ok(0) => break,
Ok(len) => sender.ack(len),
Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) if err.kind() == io::ErrorKind::WouldBlock => break,
Err(err) => return Err(err),
}
}
if sender.origin() >= SENDER_DROP_OF_THRESHOLD {
sender.drop_off_origin();
}
Ok(())
}
}
impl<R: Read> ReadExt for R {}
impl<W: Write> WriteExt for W {}
#[cfg(test)]
mod tests {
use super::*;
struct Stream {
left: usize,
eof: bool,
reads: usize,
}
impl Read for Stream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.reads += 1;
if self.left == 0 {
return match self.eof {
true => Ok(0),
false => Err(io::Error::from(io::ErrorKind::WouldBlock)),
};
}
let len = usize::min(self.left, buf.len());
buf[..len].fill(0xAA);
self.left -= len;
Ok(len)
}
}
#[test]
fn read_eof() {
let mut buffer = Buf::from(&[0xCC; 4][..]);
let mut reader = Stream { left: 8, eof: true, reads: 0 };
let (len, eof) = reader.read_nb_to_cdr(&mut buffer).unwrap();
assert_eq!(len, 8);
assert!(eof);
assert_eq!(buffer.as_slice(), [&[0xCC; 4][..], &[0xAA; 8]].concat());
}
#[test]
fn read_would_block() {
let mut buffer = Buf::new();
let mut reader = Stream { left: 0, eof: false, reads: 0 };
let (len, eof) = reader.read_nb_to_cdr(&mut buffer).unwrap();
assert_eq!(len, 0);
assert!(!eof);
assert!(buffer.is_empty());
}
#[test]
fn read_reserved() {
let mut buffer = Buf::new();
let mut reader = Stream { left: 100_000, eof: false, reads: 0 };
buffer.make_mut().try_reserve(100_000).unwrap();
let (len, eof) = reader.read_nb_to_cdr(&mut buffer).unwrap();
assert_eq!(len, 100_000);
assert!(!eof);
assert_eq!(buffer.len(), 100_000);
assert_eq!(reader.reads, 2);
}
}