parent
c05d9f8304
commit
5645ff417c
@ -0,0 +1,49 @@
|
|||||||
|
//! Extensions
|
||||||
|
use bytes::Buf;
|
||||||
|
use std::io::BufRead;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct BufIter<B: ?Sized>(B);
|
||||||
|
|
||||||
|
pub trait BufIterExt
|
||||||
|
{
|
||||||
|
fn chunks_iter(self) -> BufIter<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized + Buf> Iterator for BufIter<T>
|
||||||
|
{
|
||||||
|
type Item = bytes::Bytes;
|
||||||
|
fn next(&mut self) -> Option<Self::Item>
|
||||||
|
{
|
||||||
|
if self.0.has_remaining() {
|
||||||
|
Some(self.0.copy_to_bytes(self.0.chunk().len()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: Buf> BufIterExt for B
|
||||||
|
{
|
||||||
|
fn chunks_iter(self) -> BufIter<Self> {
|
||||||
|
BufIter(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub struct BufReadIter<B: ?Sized>(usize, B);
|
||||||
|
|
||||||
|
pub trait BufReadExt
|
||||||
|
{
|
||||||
|
fn chunks_iter(self, sz: usize) -> BufReadIter<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: ?Sized + BufRead> Iterator for BufReadIter<B>
|
||||||
|
{
|
||||||
|
type Item = bytes::Bytes;
|
||||||
|
fn next(&mut self) -> Option<Self::Item>
|
||||||
|
{
|
||||||
|
self.1.read_exact(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
@ -1,4 +1,117 @@
|
|||||||
|
|
||||||
//mod pool; A)JR AOISJOAIJOIA JODIJAOSI JDFUCK THIS DOESN@T WORK FUCK ATOMICREFCELL FUCK YOU FFUCK EVERYTHING AAAAAAAAAAAAA
|
//mod ext; use ext::*;
|
||||||
pub mod encode;
|
mod encode;
|
||||||
pub mod hash;
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in new issue