use crate::check_hashtype;
use crate::hasher::Hasher;
use crate::sample;
use crate::util::unwrap_try_into;
use crate::GenericResult;
use crate::SampleHash;
use std::collections::HashSet;
use std::convert::TryInto;
use std::path::Path;
#[derive(Eq, PartialEq, Clone, Hash, Debug)]
pub struct ContentHash {
pub sha256: SampleHash,
pub sha1: SampleHash,
pub md5: SampleHash,
}
impl Default for ContentHash {
fn default() -> Self {
ContentHash {
sha256: sample!("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" => sha256),
sha1: sample!("da39a3ee5e6b4b0d3255bfef95601890afd80709" => sha1),
md5: sample!("d41d8cd98f00b204e9800998ecf8427e" => md5),
}
}
}
impl ContentHash {
pub fn new(
sha256: impl TryInto<SampleHash>,
sha1: impl TryInto<SampleHash>,
md5: impl TryInto<SampleHash>,
) -> GenericResult<Self> {
Ok(ContentHash {
sha256: check_hashtype!(unwrap_try_into(sha256)? => sha256)?,
sha1: check_hashtype!(unwrap_try_into(sha1)? => sha1)?,
md5: check_hashtype!(unwrap_try_into(md5)? => md5)?,
})
}
pub fn of_file(path: impl AsRef<Path>) -> GenericResult<Self> {
let mut f = std::fs::File::open(path)?;
let mut hasher = Hasher::default();
std::io::copy(&mut f, &mut hasher)?;
Ok(hasher.digests())
}
}
pub fn remove_overlap(
target: impl IntoIterator<Item = impl std::convert::TryInto<SampleHash>>,
blacklist: impl IntoIterator<Item = ContentHash>,
) -> HashSet<SampleHash> {
let target: HashSet<SampleHash> = SampleHash::uniquify(target);
let blacklist: HashSet<SampleHash> = blacklist
.into_iter()
.map(|x| x.into_iter())
.flat_map(|x| x)
.collect();
target.difference(&blacklist).cloned().collect()
}
impl IntoIterator for ContentHash {
type Item = SampleHash;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
vec![self.sha256, self.sha1, self.md5].into_iter()
}
}