//! Hashing //use super::pool; use digest::{ Digest, DynDigest, Output, }; use std::marker::PhantomData; use std::{ fmt, }; #[derive(Debug, Clone, PartialEq, Eq)] pub struct ParallelDigest(usize, PhantomData D>); pub struct ParallelHash(Vec>); impl fmt::Display for ParallelHash { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use crate::encode::*; let mut d = D::new(); write!(f, "{}:", self.0.len())?; for output in self.0.iter() { d.update(&output[..]); } HexEncoder::encode_slice(&HexEncoder, &d.finalize()[..], f) } } impl ParallelDigest { /// Create a new digest pub const fn new(chunk: usize) -> Self { Self(chunk, PhantomData) } /// Compute a parallel digest from `data`. #[inline] pub fn digest(&self, data: impl AsRef<[u8]>) -> ParallelHash { ParallelHash(phash_digest_into::(data.as_ref(), self.0)) } } #[inline(always)] fn phash_raw<'a, T: Send, F: 'a>(data: &'a [u8], chunk: usize, digest: F) -> impl rayon::iter::IndexedParallelIterator + 'a where F: Fn(&[u8]) -> T + Send + Sync { use rayon::prelude::*; data.par_chunks(chunk).map(digest) } #[inline(always)] fn into_output<'a, T,F, U>(data: &'a [u8], chunk: usize, func: F) -> Vec where F: FnOnce(&'a [u8], usize) -> U, U: rayon::iter::IndexedParallelIterator + 'a { let mut output = Vec::with_capacity(1 + (data.len() / chunk)); func(data, chunk).collect_into_vec(&mut output); output } #[inline(always)] pub(crate) fn phash_raw_into(data: &[u8], chunk: usize, digest: F) -> Vec//Vec> where F: Fn(&[u8]) -> T + Send + Sync { use rayon::prelude::*; let mut output = Vec::with_capacity(1 + (data.len() / chunk)); phash_raw(data, chunk, digest) .collect_into_vec(&mut output); output } /* pub(crate) fn phash_pool<'a, D: Digest + digest::FixedOutputReset + Send + Sync + 'a>(data: &'a [u8], chunk: usize) -> impl rayon::iter::IndexedParallelIterator> + 'a { let pool = pool::Pool::new_with(rayon::max_num_threads(), D::new); phash_raw(data.as_ref(), chunk, move |range| { let mut digest = pool.take_one_or_else(D::new); ::update(&mut digest, range); digest.finalize_reset() }) } #[inline] pub(crate) fn phash_pool_into(data: &[u8], chunk: usize) -> Vec> { into_output(data, chunk, phash_pool::) } */ pub(crate) fn phash_digest<'a, D: Digest>(data: &'a [u8], chunk: usize) -> impl rayon::iter::IndexedParallelIterator> + 'a where Output: Send { phash_raw(data, chunk, |range| { let mut digest = D::new(); digest.update(range); digest.finalize() }) } pub(crate) fn phash_digest_into<'a, D: Digest>(data: &[u8], chunk: usize) -> Vec> where Output: Send { into_output(data, chunk, phash_digest::) } /* fn phash(data: impl AsRef<[u8]>, chunk: usize) -> ParallelHash { }*/