#![allow(unknown_lints)]
#![allow(bare_trait_objects)]
#![allow(ellipsis_inclusive_range_patterns)]
use super::errors::{Error, ErrorKind};
use std::cmp;
use std::io;
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum PacketType {
Flush,
Delim,
Data(usize),
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct Packet {
typ: PacketType,
data: Vec<u8>,
}
impl Packet {
pub fn new(t: PacketType, data: &[u8]) -> Self {
Packet {
typ: t,
data: data.to_vec(),
}
}
fn new_from_vec(t: PacketType, vec: Vec<u8>) -> Self {
Packet { typ: t, data: vec }
}
pub fn packet_type(&self) -> PacketType {
self.typ
}
pub fn data(&self) -> Option<&[u8]> {
match self.typ {
PacketType::Data(_) => Some(&self.data),
_ => None,
}
}
}
pub struct Reader<R: io::Read> {
rdr: R,
buf: [u8; 65536],
off: usize,
len: usize,
}
impl<R: io::Read> Reader<R> {
const MAX_PACKET_LEN: usize = 65516;
pub fn new(rdr: R) -> Self {
Reader {
rdr,
buf: [0u8; 65536],
off: 0,
len: 0,
}
}
fn read_one(rdr: &mut R, buf: &mut [u8]) -> Result<PacketType, Error> {
let mut hdr = [0u8; 4];
rdr.read_exact(&mut hdr)?;
let size = Self::parse_header(hdr)? as usize;
match size {
0 => Ok(PacketType::Flush),
1 => Ok(PacketType::Delim),
2 | 3 => Err(Error::new_simple(ErrorKind::BadPktlineHeader)),
n if n > Self::MAX_PACKET_LEN + 4 => {
Err(Error::new_simple(ErrorKind::BadPktlineHeader))
}
_ => {
rdr.read_exact(&mut buf[0..(size - 4)])?;
Ok(PacketType::Data(size - 4))
}
}
}
pub fn read_packet(&mut self) -> Result<Packet, Error> {
let mut hdr = [0u8; 4];
self.rdr.read_exact(&mut hdr)?;
let size = Self::parse_header(hdr)? as usize;
match size {
0 => Ok(Packet::new(PacketType::Flush, b"")),
1 => Ok(Packet::new(PacketType::Delim, b"")),
2 | 3 => Err(Error::new_simple(ErrorKind::BadPktlineHeader)),
_ => {
let mut v = vec![0u8; size - 4];
self.rdr.read_exact(&mut v)?;
Ok(Packet::new_from_vec(PacketType::Data(size - 4), v))
}
}
}
fn parse_header(buf: [u8; 4]) -> Result<u16, Error> {
let x: Result<Vec<u16>, Error> = buf
.iter()
.enumerate()
.map(|(i, x)| {
let v = match *x {
b'0'...b':' => x - b'0',
b'a'...b'g' => x - b'a' + 10,
_ => return Err(Error::new_simple(ErrorKind::BadPktlineHeader)),
};
Ok((v as u16) << ((3 - i) * 4))
})
.collect();
Ok(x?.into_iter().sum())
}
pub fn iter(&mut self) -> iter::ReaderIterator<'_, R> {
iter::ReaderIterator::new(self)
}
}
impl<R: io::Read> io::Read for Reader<R> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
let n = cmp::min(self.len - self.off, buf.len());
if n > 0 {
buf[0..n].copy_from_slice(&self.buf[self.off..self.off + n]);
if n == self.len - self.off {
self.off = 0;
self.len = 0;
} else {
self.off += n;
}
return Ok(n);
}
loop {
let (r, copy) = if buf.len() >= Self::MAX_PACKET_LEN {
(Self::read_one(&mut self.rdr, buf), false)
} else {
(Self::read_one(&mut self.rdr, &mut self.buf), true)
};
let n = match (r, copy) {
(Ok(PacketType::Delim), _) => return Ok(0),
(Ok(PacketType::Flush), _) => return Ok(0),
(Ok(PacketType::Data(0)), false) => n,
(Ok(PacketType::Data(n)), false) => return Ok(n),
(Ok(PacketType::Data(n)), true) => n,
(Err(e), _) => return Err(e.into()),
};
if n > 0 {
let c = cmp::min(n, buf.len());
buf[0..c].copy_from_slice(&self.buf[0..c]);
self.len = n;
self.off = c;
return Ok(c);
}
}
}
}
pub struct Writer<W: io::Write> {
writer: W,
}
impl<W: io::Write> Writer<W> {
const MAX_PACKET_LEN: usize = 65516;
pub fn new(writer: W) -> Self {
Writer { writer }
}
fn write_one(writer: &mut W, buf: &[u8]) -> Result<usize, Error> {
let header = format!("{:04x}", buf.len() + 4);
writer.write_all(header.as_bytes())?;
writer.write_all(buf)?;
Ok(buf.len())
}
pub fn write_packet(&mut self, pkt: &Packet) -> Result<usize, Error> {
match pkt.packet_type() {
PacketType::Flush => {
self.writer.write_all(b"0000")?;
self.writer.flush()?;
Ok(4)
}
PacketType::Delim => {
self.writer.write_all(b"0001")?;
Ok(4)
}
PacketType::Data(_) => Self::write_one(
&mut self.writer,
pkt.data()
.ok_or_else(|| Error::new_simple(ErrorKind::InvalidPacket))?,
),
}
}
}
impl<W: io::Write> io::Write for Writer<W> {
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
let mut total = 0;
for chunk in buf.chunks(Self::MAX_PACKET_LEN) {
total += match Self::write_one(&mut self.writer, chunk) {
Ok(sz) => sz,
Err(e) => return Err(e.into()),
}
}
Ok(total)
}
fn flush(&mut self) -> Result<(), io::Error> {
self.writer.flush()
}
}
mod iter {
use super::{Packet, Reader};
use crate::errors::Error;
use std::io;
use std::iter;
pub struct ReaderIterator<'a, R: io::Read> {
rdr: &'a mut Reader<R>,
}
impl<'a, R: io::Read> ReaderIterator<'a, R> {
pub fn new(rdr: &'a mut Reader<R>) -> Self {
ReaderIterator { rdr }
}
}
impl<'a, R: io::Read> iter::Iterator for ReaderIterator<'a, R> {
type Item = Result<Packet, Error>;
fn next(&mut self) -> Option<Result<Packet, Error>> {
match self.rdr.read_packet() {
Ok(x) => Some(Ok(x)),
Err(ref e) if e.io_kind() == io::ErrorKind::UnexpectedEof => None,
Err(e) => Some(Err(e)),
}
}
}
}
#[cfg(test)]
mod tests {
use super::{Error, ErrorKind};
use super::{PacketType, Reader, Writer};
use std::io;
use std::io::Write;
fn reader_from_buf<'a>(buf: &'a [u8]) -> Reader<io::Cursor<&'a [u8]>> {
Reader::new(io::Cursor::new(buf))
}
fn writer() -> Writer<io::Cursor<Vec<u8>>> {
Writer::new(io::Cursor::new(Vec::new()))
}
fn check_packet(buf: &[u8], r: Result<(PacketType, Option<&[u8]>), Error>) {
let mut rdr = reader_from_buf(buf);
let mut v = vec![0u8; 65536];
let pt = Reader::read_one(&mut rdr.rdr, &mut v);
let data: Result<(PacketType, Option<&[u8]>), Error> = match pt {
Ok(PacketType::Data(x)) => {
v.truncate(x);
Ok((PacketType::Data(x), Some(&v)))
}
Ok(x) => Ok((x, None)),
Err(e) => Err(e),
};
assert_eq!(data, r);
let mut rdr = reader_from_buf(buf);
let pkt = rdr.read_packet();
let unwrapped = match &pkt {
&Ok(ref p) => Some(p.clone()),
&Err(_) => None,
};
assert_eq!(
pkt.map(|p| (p.packet_type().clone(), p.data().map(|x| x.to_vec()))),
r.map(|(pt, sl)| (pt.clone(), sl.map(|x| x.to_vec())))
);
if let Some(pkt) = unwrapped {
let mut wrtr = writer();
wrtr.write_packet(&pkt).unwrap();
assert_eq!(wrtr.writer.into_inner(), buf);
}
}
fn pattern_of_size(n: usize) -> Vec<u8> {
(0..n)
.map(|x| (x + (x >> 8) + (x >> 16) + (x >> 24)) as u8)
.collect()
}
#[test]
fn pktline_headers() {
assert_eq!(Reader::<io::Cursor<&[u8]>>::parse_header(*b"0000"), Ok(0));
assert_eq!(Reader::<io::Cursor<&[u8]>>::parse_header(*b"0001"), Ok(1));
assert_eq!(Reader::<io::Cursor<&[u8]>>::parse_header(*b"0004"), Ok(4));
assert_eq!(
Reader::<io::Cursor<&[u8]>>::parse_header(*b"ffff"),
Ok(65535)
);
assert_eq!(
Reader::<io::Cursor<&[u8]>>::parse_header(*b"2204"),
Ok(8708)
);
assert_eq!(
Reader::<io::Cursor<&[u8]>>::parse_header(*b"cafe"),
Ok(51966)
);
assert_eq!(
Reader::<io::Cursor<&[u8]>>::parse_header(*b"cafE"),
Err(Error::new_simple(ErrorKind::BadPktlineHeader))
);
assert_eq!(
Reader::<io::Cursor<&[u8]>>::parse_header(*b"\xc2\xa9fe"),
Err(Error::new_simple(ErrorKind::BadPktlineHeader))
);
}
#[test]
fn parse_packet() {
check_packet(b"0000", Ok((PacketType::Flush, None)));
check_packet(b"0001", Ok((PacketType::Delim, None)));
check_packet(b"0004", Ok((PacketType::Data(0), Some(b""))));
check_packet(b"0005a", Ok((PacketType::Data(1), Some(b"a"))));
check_packet(
b"0046\xff\xfee3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
Ok((
PacketType::Data(66),
Some(b"\xff\xfee3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"),
)),
);
}
#[test]
fn write_data() {
let mut wrtr = writer();
wrtr.write(b"abc").unwrap();
wrtr.write(b"\xff\xfe\xc2\xa90123456").unwrap();
assert_eq!(
wrtr.writer.into_inner(),
b"0007abc000f\xff\xfe\xc2\xa90123456"
);
}
#[test]
fn write_data_large() {
let mut wrtr = writer();
let buf = pattern_of_size(65536);
let expected: [&[u8]; 4] = [b"fff0", &buf[0..65516], b"0018", &buf[65516..65536]];
let expected = expected.concat();
wrtr.write(&buf).unwrap();
wrtr.flush().unwrap();
assert_eq!(expected, wrtr.writer.into_inner());
}
#[test]
fn read_data_large() {
let buf = pattern_of_size(1048576);
for chunk_size in &[10, 17, 2204, 32768, 32771, 65516] {
let mut input: Vec<u8> = buf
.chunks(*chunk_size)
.flat_map(|x| {
let mut vec = format!("{:04x}", x.len() + 4).as_bytes().to_vec();
vec.extend(x);
vec
})
.collect();
input.extend(b"0000");
let mut rdr = reader_from_buf(&input);
let mut cursor = io::Cursor::new(Vec::new());
io::copy(&mut rdr, &mut cursor).unwrap();
let actual = cursor.into_inner();
assert_eq!(buf, actual);
}
}
}