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

//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");
}
}