//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 = [ 10 u8 ; 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" ) ;
}
}