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.
118 lines
2.6 KiB
118 lines
2.6 KiB
|
|
//mod ext; use ext::*;
|
|
mod encode;
|
|
mod hash;
|
|
|
|
pub use digest;
|
|
|
|
pub use hash::{
|
|
ParallelHashOutput,
|
|
ParallelHash,
|
|
ParallelDigest,
|
|
};
|
|
|
|
pub type DefaultDigest = sha2::Sha256;
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
|
pub struct Builder<D= DefaultDigest>
|
|
{
|
|
digest: std::marker::PhantomData<D>,
|
|
chunk_size: Option<std::num::NonZeroUsize>,
|
|
}
|
|
|
|
impl Builder<DefaultDigest>
|
|
{
|
|
#[inline]
|
|
pub fn create_default() -> ParallelDigest<DefaultDigest>
|
|
{
|
|
Self::new().create()
|
|
}
|
|
pub const fn new_default() -> Self
|
|
{
|
|
Self {
|
|
digest: std::marker::PhantomData,
|
|
chunk_size: None
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<D: digest::Digest> Builder<D>
|
|
{
|
|
//pub type Digest = D;
|
|
pub const fn new() -> Self
|
|
{
|
|
Self {
|
|
digest: std::marker::PhantomData,
|
|
chunk_size: None
|
|
}
|
|
}
|
|
pub const fn with_digest<N: digest::Digest>(self) -> Builder<N>
|
|
{
|
|
Builder {
|
|
chunk_size: self.chunk_size,
|
|
digest: std::marker::PhantomData,
|
|
}
|
|
}
|
|
pub const fn with_chunk_size(self, chunk_size: usize) -> Self
|
|
{
|
|
Self {
|
|
chunk_size: std::num::NonZeroUsize::new(chunk_size),
|
|
..self
|
|
}
|
|
}
|
|
}
|
|
impl<D: digest::Digest + Send + Sync> Builder<D>
|
|
{
|
|
#[inline]
|
|
pub fn chunk_size(&self) -> usize
|
|
{
|
|
extern "C" {
|
|
fn getpagesize() -> std::os::raw::c_int;
|
|
}
|
|
self.chunk_size
|
|
.or_else(|| unsafe { std::num::NonZeroUsize::new(getpagesize().try_into().expect("Failed to get page size")) })
|
|
.expect("Failed to get page size: cannot be zero")
|
|
.get()
|
|
}
|
|
#[inline]
|
|
pub fn create(self) -> ParallelDigest<D>
|
|
{
|
|
ParallelDigest::<D>::new(self.chunk_size())
|
|
}
|
|
#[inline]
|
|
pub fn digest_slice(self, slice: impl AsRef<[u8]>) -> ParallelHash<D>
|
|
{
|
|
ParallelDigest::<D>::digest_slice(self.chunk_size(), slice)
|
|
}
|
|
}
|
|
|
|
impl<D: digest::Digest + Send + Sync> From<Builder<D>> for ParallelDigest<D>
|
|
{
|
|
#[inline]
|
|
fn from(from: Builder<D>) -> Self
|
|
{
|
|
from.create()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests
|
|
{
|
|
use super::*;
|
|
#[test]
|
|
fn parallel_hash_specific_cs()
|
|
{
|
|
const CHUNK_SIZE: usize = 0;
|
|
let slice = [10u8; 4096 << 2];//b"One two three for fize size seven eight.";
|
|
let mut digest = Builder::new().with_chunk_size(CHUNK_SIZE).create();
|
|
digest.append_slice(slice);
|
|
let digest= digest.complete().finalize();
|
|
println!("digest: {digest}");
|
|
|
|
assert_eq!(digest, Builder::new_default().with_chunk_size(CHUNK_SIZE).digest_slice(slice).finalize(), "phash of same input produced different output");
|
|
|
|
assert_ne!(digest, Builder::new_default().with_chunk_size(CHUNK_SIZE).digest_slice(&slice[..8]).finalize(), "phash of differing input produced same output");
|
|
}
|
|
}
|
|
|