use ::{Error, Reader, Result, Writer};
use std::io;
use std::result;
use std::io::{Read, Write};
use std::mem::{size_of, transmute};
const FILE_HEADER: &'static [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 = try!(file.read(&mut header));
if read_length == FILE_HEADER.len() && &*header.into_boxed_slice() == FILE_HEADER {
return Ok(FileReader { file: file });
} else {
return Err(Error::CorruptSegmentHeader);
}
}
}
enum ReadExactError {
Partial(usize),
Other(io::Error),
}
fn read_exact(read: &mut 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 header_ptr: *const i32 = unsafe { transmute(&header[0]) };
let body_length_number = unsafe { ::std::ptr::read::<i32>(header_ptr) };
let body_length = body_length_number as usize;
let mut full_buffer = Vec::with_capacity(body_length);
unsafe {
full_buffer.set_len(body_length);
}
match read_exact(&mut self.file, &mut full_buffer) {
Ok(()) => {
return Ok(Some(full_buffer));
}
Err(ReadExactError::Partial(bytes_read)) => {
return Err(Error::InsufficientLength(body_length - bytes_read));
}
Err(ReadExactError::Other(io_error)) => {
return 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 try!(file.write(FILE_HEADER)) == FILE_HEADER.len() {
Ok(FileWriter { file: file })
} else {
Err(Error::CorruptSegmentHeader)
}
}
pub fn write_multiple(&mut self, bufs: &[&[u8]]) -> Result<()> {
let value = bufs.iter().fold(0, |sum, buf| sum + buf.len()) as i32;
let header_ptr: *const u8 = unsafe { transmute(&value) };
let header_length = size_of::<i32>();
let slice = unsafe { ::std::slice::from_raw_parts(header_ptr, header_length) };
try!(self.file.write_all(slice));
for buf in bufs {
try!(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])
}
}