use crate::{Error, Reader, Result, Writer};
use std::io;
use std::result;
use std::io::{Read, Write};
const FILE_HEADER: &[u8] = b"DFSN";
#[derive(Debug)]
pub struct FileReader<T>
where T: Read
{
file: T,
}
impl<T> FileReader<T> where T: Read {
pub fn new(mut file: T) -> Result<FileReader<T>> {
let mut header = vec![0u8; FILE_HEADER.len()];
let read_length = file.read(&mut header)?;
if read_length == FILE_HEADER.len() && &*header.into_boxed_slice() == FILE_HEADER {
Ok(FileReader { file })
} else {
Err(Error::CorruptSegmentHeader)
}
}
}
enum ReadExactError {
Partial(usize),
Other(io::Error),
}
fn read_exact(read: &mut dyn Read, mut buf: &mut [u8]) -> result::Result<(), ReadExactError> {
let mut bytes_read = 0;
while !buf.is_empty() {
match read.read(buf) {
Ok(0) => break,
Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; bytes_read += n; }
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(ReadExactError::Other(e)),
}
}
if !buf.is_empty() {
Err(ReadExactError::Partial(bytes_read))
} else {
Ok(())
}
}
impl<T> Reader for FileReader<T> where T: Read {
fn read(&mut self) -> Result<Option<Vec<u8>>> {
let mut header = [0u8; 4];
match read_exact(&mut self.file, &mut header) {
Ok(()) => {
}
Err(ReadExactError::Partial(bytes_read)) => {
if bytes_read == 0 {
return Ok(None);
} else {
return Err(Error::CorruptMsgHeader);
}
}
Err(ReadExactError::Other(io_error)) => {
return Err(io_error.into());
}
}
let body_length_number = i32::from_le_bytes(header);
let body_length = body_length_number as usize;
let mut full_buffer = vec![0u8; body_length];
match read_exact(&mut self.file, &mut full_buffer) {
Ok(()) => {
Ok(Some(full_buffer))
}
Err(ReadExactError::Partial(bytes_read)) => {
Err(Error::InsufficientLength(body_length - bytes_read))
}
Err(ReadExactError::Other(io_error)) => {
Err(io_error.into())
}
}
}
}
impl<T> Iterator for FileReader<T> where T: Read {
type Item = Result<Vec<u8>>;
fn next(&mut self) -> Option<Result<Vec<u8>>> {
match self.read() {
Ok(Some(data)) => Some(Ok(data)),
Ok(None) => None,
Err(error) => Some(Err(error)),
}
}
}
#[derive(Debug)]
pub struct FileWriter<T>
where T: Write
{
file: T,
}
impl<T> FileWriter<T> where T: Write {
pub fn new(mut file: T) -> Result<FileWriter<T>> {
if file.write(FILE_HEADER)? == FILE_HEADER.len() {
Ok(FileWriter { file })
} else {
Err(Error::CorruptSegmentHeader)
}
}
pub fn write_multiple(&mut self, bufs: &[&[u8]]) -> Result<()> {
let total_length_i32 = bufs.iter().fold(0, |sum, buf| sum + buf.len()) as i32;
let header: [u8; 4] = total_length_i32.to_le_bytes();
self.file.write_all(&header)?;
for buf in bufs {
self.file.write_all(buf)?;
}
Ok(())
}
}
impl<T> Writer for FileWriter<T> where T: Write {
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<()> {
self.write_multiple(&[buf])
}
}