extern crate blake2_rfc as b2;
extern crate tempdir;
use tempdir::TempDir;
use std::io::{Read, Write, Result, Error, ErrorKind};
use std::collections::HashMap;
use std::path::PathBuf;
use self::b2::blake2b::Blake2b;
use hash::{Hash32, Hasher32, NewHash};
use backend::Backend;
use store::Store;
use content::Content;
pub struct BlakeWrap(Option<Blake2b>);
impl Hasher32 for BlakeWrap {
fn finalize(&mut self) -> Hash32 {
let r = self.0.take().expect("Hasher finalized only once").finalize();
let s = r.as_bytes();
let mut arr = [0u8; 32];
for i in 0..32 {
arr[i] = s[i]
}
Hash32(arr)
}
}
impl Write for BlakeWrap {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
let msg = "Write to finished hasher";
let mut res = Err(Error::new(ErrorKind::Other, msg));
self.0.iter_mut().next().map(|hasher| res = hasher.write(buf));
res
}
fn flush(&mut self) -> Result<()> {
let msg = "Flushing finished hasher";
let mut res = Err(Error::new(ErrorKind::Other, msg));
self.0.iter_mut().next().map(|hasher| res = hasher.flush());
res
}
}
impl Backend for TempDir {
fn store(
&mut self,
source: &Fn(&mut Write, &mut Backend) -> Result<()>,
newhash: &NewHash,
) -> Result<Hash32> {
PathBuf::from(self.path()).store(source, newhash)
}
fn request(
&self,
hash: &Hash32,
read: &Fn(&mut Read) -> Result<()>,
) -> Result<()> {
PathBuf::from(self.path()).request(hash, read)
}
}
pub fn membackend() -> Box<Backend> {
Box::new(HashMap::<Hash32, Vec<u8>>::new())
}
pub fn diskbackend() -> Box<Backend> {
Box::new(TempDir::new("content_pathbuf").unwrap())
}
pub fn store<T: Content>() -> Store<T> {
Store::new(membackend(), Box::new(|| {
Box::new(BlakeWrap(Some(Blake2b::new(32))))
}))
}
pub fn diskstore<T: Content>() -> Store<T> {
Store::new(diskbackend(), Box::new(|| {
Box::new(BlakeWrap(Some(Blake2b::new(32))))
}))
}