use std::vec;
use crate::{general::ConnectionReader, message::Message};
#[cfg(test)]
use crate::message::{MessageHeader, MessageType};
use async_trait::async_trait;
#[derive(Debug)]
pub struct Reader {
data: Vec<u8>,
eof_returned: bool,
close_on_eof: bool,
}
impl Reader {
pub fn new() -> Self {
Self {
data: Vec::new(),
eof_returned: false,
close_on_eof: false,
}
}
pub fn add_message(&mut self, msg: Message) {
let mut head: [u8; 13] = [0; 13];
let body = msg.serialize(&mut head);
self.data.extend_from_slice(&head[..]);
self.data.extend_from_slice(body);
}
pub fn add_bytes(&mut self, tmp: &[u8]) {
self.data.extend_from_slice(tmp);
}
pub fn close(&mut self) {
self.close_on_eof = true;
}
}
#[async_trait]
impl ConnectionReader for Reader {
async fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let data_length = self.data.len();
let buf_length = buf.len();
let read_length = std::cmp::min(data_length, buf_length);
if read_length == 0 && self.eof_returned && self.close_on_eof {
return Err(std::io::Error::from(std::io::ErrorKind::BrokenPipe));
}
if read_length == 0 {
self.eof_returned = true;
}
for (index, tmp) in self.data.drain(0..read_length).enumerate() {
buf[index] = tmp;
}
Ok(read_length)
}
async fn read_full(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let data_length = self.data.len();
if data_length == 0 {
return Ok(0);
}
let buf_length = buf.len();
if buf_length > data_length {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"Buffer has less Data than requested",
));
}
for (index, tmp) in self.data.drain(0..buf_length).enumerate() {
buf[index] = tmp;
}
Ok(buf_length)
}
}
#[test]
fn new_reader() {
let tmp = Reader::new();
assert_eq!(Vec::<u8>::new(), tmp.data);
}
#[test]
fn new_add_message() {
let mut tmp = Reader::new();
let msg = Message::new(MessageHeader::new(13, MessageType::Data, 13), vec![0; 13]);
tmp.add_message(msg);
let mut expected_data = vec![13u8, 0, 0, 0, 3, 13, 0, 0, 0, 0, 0, 0, 0];
expected_data.append(&mut vec![0; 13]);
assert_eq!(expected_data, tmp.data)
}
#[tokio::test]
async fn read_message() {
let mut tmp = Reader::new();
let msg = Message::new(MessageHeader::new(13, MessageType::Data, 10), vec![1; 10]);
tmp.add_message(msg);
let mut head_read = [0; 13];
let head_result = tmp.read_full(&mut head_read).await;
assert_eq!(true, head_result.is_ok());
assert_eq!(13, head_result.unwrap());
assert_eq!(
&vec![13u8, 0, 0, 0, 3, 10, 0, 0, 0, 0, 0, 0, 0],
&head_read[..]
);
let mut body_read = [0; 10];
let body_result = tmp.read_full(&mut body_read).await;
assert_eq!(true, body_result.is_ok());
assert_eq!(10, body_result.unwrap());
assert_eq!(&vec![1; 10], &body_read[..]);
let mut empty = [0; 10];
let eof_result = tmp.read_full(&mut empty).await;
assert_eq!(true, eof_result.is_ok());
assert_eq!(0, eof_result.unwrap());
}
#[tokio::test]
async fn read_fits() {
let mut tmp = Reader::new();
tmp.add_bytes(&vec![0, 1, 2, 3, 4, 5]);
let mut buffer = [0u8; 6];
let read_result = tmp.read(&mut buffer).await;
assert_eq!(true, read_result.is_ok());
assert_eq!(6, read_result.unwrap());
assert_eq!(&vec![0, 1, 2, 3, 4, 5], &buffer);
let eof_result = tmp.read(&mut buffer).await;
assert_eq!(true, eof_result.is_ok());
assert_eq!(0, eof_result.unwrap());
}
#[tokio::test]
async fn read_buffer_is_bigger() {
let mut tmp = Reader::new();
tmp.add_bytes(&vec![0, 1, 2, 3, 4, 5]);
let mut buffer = [0u8; 8];
let read_result = tmp.read(&mut buffer).await;
assert_eq!(true, read_result.is_ok());
assert_eq!(6, read_result.unwrap());
assert_eq!(&vec![0, 1, 2, 3, 4, 5], &buffer[0..6]);
let eof_result = tmp.read(&mut buffer).await;
assert_eq!(true, eof_result.is_ok());
assert_eq!(0, eof_result.unwrap());
}
#[tokio::test]
async fn read_buffer_is_smaller_multiple_reads() {
let mut tmp = Reader::new();
tmp.add_bytes(&vec![0, 1, 2, 3, 4, 5]);
let mut buffer = [0u8; 3];
let read_result = tmp.read(&mut buffer).await;
assert_eq!(true, read_result.is_ok());
assert_eq!(3, read_result.unwrap());
assert_eq!(&vec![0, 1, 2], &buffer[0..3]);
let read_result = tmp.read(&mut buffer).await;
assert_eq!(true, read_result.is_ok());
assert_eq!(3, read_result.unwrap());
assert_eq!(&vec![3, 4, 5], &buffer[0..3]);
let eof_result = tmp.read(&mut buffer).await;
assert_eq!(true, eof_result.is_ok());
assert_eq!(0, eof_result.unwrap());
}
#[tokio::test]
async fn read_fits_with_close() {
let mut tmp = Reader::new();
tmp.add_bytes(&vec![0, 1, 2, 3, 4, 5]);
tmp.close();
let mut buffer = [0u8; 6];
let read_result = tmp.read(&mut buffer).await;
assert_eq!(true, read_result.is_ok());
assert_eq!(6, read_result.unwrap());
assert_eq!(&vec![0, 1, 2, 3, 4, 5], &buffer);
let eof_result = tmp.read(&mut buffer).await;
assert_eq!(true, eof_result.is_ok());
assert_eq!(0, eof_result.unwrap());
let close_result = tmp.read(&mut buffer).await;
assert_eq!(true, close_result.is_err());
}