use std::io;
use std::io::Write;
use adler32::RollingAdler32;
use byteorder::LittleEndian;
use byteorder::WriteBytesExt;
use misc::*;
pub fn adler_write_hash <
PrefixFunction: Fn () -> String,
> (
prefix_function: PrefixFunction,
adler_write: & mut AdlerWrite,
) -> Result <(), String> {
let calculated_hash =
adler_write.hash ();
io_result_with_prefix (
|| format! (
"{}Error writing adler32 checksum: ",
prefix_function ()),
adler_write.write_u32::<LittleEndian> (
calculated_hash),
) ?;
Ok (())
}
pub trait AdlerWrite : CloseableWrite {
fn byte_count (& self) -> usize;
fn hash (& self) -> u32;
fn update (
& mut self,
data: & [u8],
);
}
pub struct AdlerWriter <
Target: Write,
> {
target: Target,
adler: RollingAdler32,
byte_count: usize,
}
impl <
Target: Write,
> AdlerWriter <Target> {
pub fn new (
target: Target,
) -> AdlerWriter <Target> {
AdlerWriter {
target: target,
adler: RollingAdler32::new (),
byte_count: 0,
}
}
}
impl <
Target: CloseableWrite,
> AdlerWrite for AdlerWriter <Target> {
fn byte_count (& self) -> usize {
self.byte_count
}
fn hash (& self) -> u32 {
self.adler.hash ()
}
fn update (
& mut self,
data: & [u8],
) {
self.adler.update_buffer (
data);
self.byte_count +=
data.len ();
}
}
impl <
Target: CloseableWrite,
> Write for AdlerWriter <Target> {
fn write (
& mut self,
buffer: & [u8],
) -> Result <usize, io::Error> {
match self.target.write (
buffer) {
Ok (write_size) => {
self.adler.update_buffer (
& buffer [0 .. write_size]);
self.byte_count +=
write_size;
Ok (write_size)
},
Err (error) =>
Err (error),
}
}
fn flush (
& mut self,
) -> Result <(), io::Error> {
self.target.flush ()
}
}
impl <
Target: CloseableWrite,
> CloseableWrite for AdlerWriter <Target> {
fn close (
& mut self,
) -> Result <(), io::Error> {
self.target.close ()
}
}