use std::fs::File;
use std::io::{Read, BufReader};
use std::net::{TcpStream, UdpSocket};
use std::borrow::BorrowMut;
use bytes::BytesMut;
pub enum StreamReadResult {
BytesRead(usize),
Finished,
Error(String),
}
pub trait StreamRead {
fn read_bytes(&mut self, bytes: &mut BytesMut, num_bytes: usize) -> StreamReadResult;
}
impl StreamRead for TcpStream {
fn read_bytes(&mut self, bytes: &mut BytesMut, num_bytes: usize) -> StreamReadResult {
read_bytes_from_reader(self, bytes, num_bytes)
}
}
impl StreamRead for BufReader<File> {
fn read_bytes(&mut self, bytes: &mut BytesMut, num_bytes: usize) -> StreamReadResult {
let result = read_bytes_from_reader(self, bytes, num_bytes);
if let StreamReadResult::BytesRead(0) = result {
return StreamReadResult::Finished;
} else {
return result;
}
}
}
impl StreamRead for UdpSocket {
fn read_bytes(&mut self, bytes: &mut BytesMut, _num_bytes: usize) -> StreamReadResult {
bytes.clear();
match self.recv(bytes).map_err(|err| format!("Udp Socket Read Error: {}", err)) {
Ok(bytes_read) => {
return StreamReadResult::BytesRead(bytes_read);
},
Err(string) => {
return StreamReadResult::Error(string);
}
}
}
}
fn read_bytes_from_reader<R: Read>(reader: &mut R, bytes: &mut BytesMut, num_bytes: usize) -> StreamReadResult {
let old_len = bytes.len();
let new_len = old_len + num_bytes;
bytes.reserve(num_bytes);
bytes.resize(new_len, 0);
let mut_bytes: &mut [u8] = bytes.borrow_mut();
let result = reader.read(&mut mut_bytes[old_len..(old_len + num_bytes)])
.map_err(|err| format!("Stream Read Error: {}", err));
match result {
Ok(bytes_read) => {
bytes.truncate(old_len + bytes_read);
return StreamReadResult::BytesRead(bytes_read);
},
Err(string) => {
return StreamReadResult::Error(string);
}
}
}