You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
3.1 KiB

//! Hashing
//use super::pool;
use digest::{
Digest,
DynDigest,
Output,
};
use std::marker::PhantomData;
use std::{
fmt,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParallelDigest<D: Digest + Send + Sync>(usize, PhantomData<fn () -> D>);
pub struct ParallelHash<D: Digest>(Vec<Output<D>>);
impl<D: Digest> fmt::Display for ParallelHash<D>
{
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<D: Digest + Send + Sync> ParallelDigest<D>
{
/// 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<D>
{
ParallelHash(phash_digest_into::<D>(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<Item = T> + '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<T>
where F: FnOnce(&'a [u8], usize) -> U,
U: rayon::iter::IndexedParallelIterator<Item = T> + '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<T: Send, F>(data: &[u8], chunk: usize, digest: F) -> Vec<T>//Vec<Output<D>>
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<Item= Output<D>> + '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);
<D as Digest>::update(&mut digest, range);
digest.finalize_reset()
})
}
#[inline]
pub(crate) fn phash_pool_into<D: Digest + digest::FixedOutputReset + Send + Sync>(data: &[u8], chunk: usize) -> Vec<Output<D>>
{
into_output(data, chunk, phash_pool::<D>)
}
*/
pub(crate) fn phash_digest<'a, D: Digest>(data: &'a [u8], chunk: usize) -> impl rayon::iter::IndexedParallelIterator<Item = Output<D>> + 'a
where Output<D>: 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<Output<D>>
where Output<D>: Send
{
into_output(data, chunk, phash_digest::<D>)
}
/*
fn phash<D: Digest + Send + Sync>(data: impl AsRef<[u8]>, chunk: usize) -> ParallelHash<D>
{
}*/