use std::io::{Read, Write};
use std::path::PathBuf;
use crate::types::ErrBox;
const BUFFER_SIZE: usize = 1024;
pub struct StdInOutReaderWriter<'a, TRead: Read, TWrite: Write> {
writer: &'a mut TWrite,
reader: &'a mut TRead,
}
impl<'a, TRead: Read, TWrite: Write> StdInOutReaderWriter<'a, TRead, TWrite> {
pub fn new(reader: &'a mut TRead, writer: &'a mut TWrite) -> Self {
StdInOutReaderWriter {
writer,
reader
}
}
pub fn send_message_kind(&mut self, message_kind: u32) -> Result<(), ErrBox> {
self.writer.write_all(&message_kind.to_be_bytes())?;
self.writer.flush()?;
Ok(())
}
pub fn send_message_part_as_u32(&mut self, value: u32) -> Result<(), ErrBox> {
self.send_message_part(&value.to_be_bytes())
}
pub fn send_message_part_as_string(&mut self, text: &str) -> Result<(), ErrBox> {
self.send_message_part(text.as_bytes())
}
pub fn send_message_part_as_path_buf(&mut self, path_buf: &PathBuf) -> Result<(), ErrBox> {
self.send_message_part_as_string(&path_buf.to_string_lossy())
}
pub fn send_message_part(&mut self, data: &[u8]) -> Result<(), ErrBox> {
self.writer.write_all(&(data.len() as u32).to_be_bytes())?;
self.writer.write_all(&data[0..std::cmp::min(BUFFER_SIZE, data.len())])?;
self.writer.flush()?;
let mut index = BUFFER_SIZE;
while index < data.len() {
self.reader.read_exact(&mut [0; 4])?;
let start_index = index;
let end_index = std::cmp::min(index + BUFFER_SIZE, data.len());
self.writer.write_all(&data[start_index..end_index])?;
self.writer.flush()?;
index += BUFFER_SIZE;
}
Ok(())
}
pub fn read_message_kind(&mut self) -> Result<u32, ErrBox> {
self.read_u32()
}
pub fn read_message_part_as_u32(&mut self) -> Result<u32, ErrBox> {
let message_part = self.read_message_part()?;
if message_part.len() != 4 {
return err!("Expected to read a message part size of 4 bytes, but was {}.", message_part.len());
}
let mut dst = [0u8; 4];
dst.clone_from_slice(&message_part[0..4]);
Ok(u32::from_be_bytes(dst))
}
pub fn read_message_part_as_string(&mut self) -> Result<String, ErrBox> {
let message_part = self.read_message_part()?;
Ok(String::from_utf8(message_part)?)
}
pub fn read_message_part_as_path_buf(&mut self) -> Result<PathBuf, ErrBox> {
let message_data = self.read_message_part()?;
Ok(PathBuf::from(std::str::from_utf8(&message_data)?))
}
pub fn read_message_part(&mut self) -> Result<Vec<u8>, ErrBox> {
let size = self.read_u32()? as usize;
let mut message_data = vec![0u8; size];
if size > 0 {
self.reader.read_exact(&mut message_data[0..std::cmp::min(BUFFER_SIZE, size)])?;
let mut index = BUFFER_SIZE;
while index < size {
self.writer.write_all(&[0; 4])?;
self.writer.flush()?;
let start_index = index;
let end_index = std::cmp::min(index + BUFFER_SIZE, size);
self.reader.read_exact(&mut message_data[start_index..end_index])?;
index += BUFFER_SIZE;
}
}
Ok(message_data)
}
fn read_u32(&mut self) -> Result<u32, ErrBox> {
let mut int_buf: [u8; 4] = [0; 4];
self.reader.read_exact(&mut int_buf)?;
Ok(u32::from_be_bytes(int_buf))
}
}