Skip to content

Commit

Permalink
digest: replace Reset trait with methods; add *into* methods
Browse files Browse the repository at this point in the history
Closes RustCrypto/hashes#86

Replaces the `Reset` trait with a set of `_reset` methods on all of the
various traits, and uses these as the default impl for the methods which
consume hashers.

Also adds a set of methods to `FixedOutput` (`finalize_fixed_into*`)
which eliminate copies by accepting an existing buffer as an argument.
  • Loading branch information
tarcieri committed Jun 9, 2020
1 parent e312a03 commit 47d5f10
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 41 deletions.
12 changes: 6 additions & 6 deletions digest/src/dev.rs
Expand Up @@ -2,7 +2,7 @@

pub use blobby;

use super::{ExtendableOutput, Reset, Update, VariableOutput, XofReader};
use super::{ExtendableOutput, Update, VariableOutput, XofReader};
use core::fmt::Debug;

/// Define test
Expand Down Expand Up @@ -51,7 +51,7 @@ mod foo {
}

// Test if reset works correctly
hasher2.reset();
hasher2.finalize_reset();
hasher2.update(input);
if hasher2.finalize().as_slice() != output {
return Some("whole message after reset");
Expand Down Expand Up @@ -101,7 +101,7 @@ pub use self::foo::{digest_test, one_million_a};
/// XOF test
pub fn xof_test<D>(input: &[u8], output: &[u8]) -> Option<&'static str>
where
D: Update + ExtendableOutput + Default + Debug + Reset + Clone,
D: Update + ExtendableOutput + Default + Debug + Clone,
{
let mut hasher = D::default();
let mut buf = [0u8; 1024];
Expand All @@ -119,7 +119,7 @@ where
}

// Test if hasher resets correctly
hasher2.reset();
hasher2.finalize_xof_reset();
hasher2.update(input);

{
Expand Down Expand Up @@ -168,7 +168,7 @@ where
/// Variable-output digest test
pub fn variable_test<D>(input: &[u8], output: &[u8]) -> Option<&'static str>
where
D: Update + VariableOutput + Reset + Debug + Clone,
D: Update + VariableOutput + Debug + Clone,
{
let mut hasher = D::new(output.len()).unwrap();
let mut buf = [0u8; 128];
Expand All @@ -182,7 +182,7 @@ where
}

// Test if reset works correctly
hasher2.reset();
hasher2.finalize_variable_reset(|_| ());
hasher2.update(input);
hasher2.finalize_variable(|res| buf.copy_from_slice(res));
if buf != output {
Expand Down
15 changes: 3 additions & 12 deletions digest/src/digest.rs
@@ -1,4 +1,4 @@
use super::{FixedOutput, Reset, Update};
use super::{FixedOutput, Update};
use generic_array::typenum::Unsigned;
use generic_array::{ArrayLength, GenericArray};

Expand Down Expand Up @@ -32,9 +32,6 @@ pub trait Digest {
/// re-creation.
fn finalize_reset(&mut self) -> Output<Self>;

/// Reset hasher instance to its initial state.
fn reset(&mut self);

/// Get output size of the hasher
fn output_size() -> usize;

Expand All @@ -49,7 +46,7 @@ pub trait Digest {
fn digest(data: &[u8]) -> Output<Self>;
}

impl<D: Update + FixedOutput + Reset + Clone + Default> Digest for D {
impl<D: Update + FixedOutput + Clone + Default> Digest for D {
type OutputSize = <Self as FixedOutput>::OutputSize;

fn new() -> Self {
Expand All @@ -72,13 +69,7 @@ impl<D: Update + FixedOutput + Reset + Clone + Default> Digest for D {
}

fn finalize_reset(&mut self) -> Output<Self> {
let res = self.clone().finalize_fixed();
self.reset();
res
}

fn reset(&mut self) {
<Self as Reset>::reset(self)
self.finalize_fixed_reset()
}

fn output_size() -> usize {
Expand Down
23 changes: 9 additions & 14 deletions digest/src/dyn_digest.rs
@@ -1,7 +1,7 @@
#![cfg(feature = "alloc")]
use alloc::boxed::Box;

use super::{FixedOutput, Reset, Update};
use super::{FixedOutput, Update};
use generic_array::typenum::Unsigned;

/// The `DynDigest` trait is a modification of `Digest` trait suitable
Expand All @@ -18,33 +18,28 @@ pub trait DynDigest {
/// Retrieve result and consume boxed hasher instance
fn finalize(self: Box<Self>) -> Box<[u8]>;

/// Reset hasher instance to its initial state.
fn reset(&mut self);

/// Get output size of the hasher
fn output_size(&self) -> usize;

/// Clone hasher state into a boxed trait object
fn box_clone(&self) -> Box<dyn DynDigest>;
}

impl<D: Update + FixedOutput + Reset + Clone + 'static> DynDigest for D {
impl<D: Update + FixedOutput + Clone + 'static> DynDigest for D {
fn update(&mut self, data: &[u8]) {
Update::update(self, data);
}

#[inline]
fn finalize_reset(&mut self) -> Box<[u8]> {
let res = self.clone().finalize_fixed().to_vec().into_boxed_slice();
Reset::reset(self);
res
}

fn finalize(self: Box<Self>) -> Box<[u8]> {
self.finalize_fixed().to_vec().into_boxed_slice()
self.clone()
.finalize_fixed_reset()
.to_vec()
.into_boxed_slice()
}

fn reset(&mut self) {
Reset::reset(self);
fn finalize(mut self: Box<Self>) -> Box<[u8]> {
self.finalize_reset()
}

fn output_size(&self) -> usize {
Expand Down
53 changes: 44 additions & 9 deletions digest/src/lib.rs
Expand Up @@ -80,7 +80,33 @@ pub trait FixedOutput {
type OutputSize: ArrayLength<u8>;

/// Retrieve result and consume hasher instance.
fn finalize_fixed(self) -> GenericArray<u8, Self::OutputSize>;
#[inline]
fn finalize_fixed(mut self) -> GenericArray<u8, Self::OutputSize>
where
Self: Sized,
{
self.finalize_fixed_reset()
}

/// Retrieve result and reset hasher instance.
#[inline]
fn finalize_fixed_reset(&mut self) -> GenericArray<u8, Self::OutputSize> {
let mut buf = Default::default();
self.finalize_fixed_into_reset(&mut buf);
buf
}

/// Retrieve result into provided buffer and consume hasher instance.
#[inline]
fn finalize_fixed_into(mut self, out: &mut GenericArray<u8, Self::OutputSize>)
where
Self: Sized,
{
self.finalize_fixed_into_reset(out);
}

/// Retrieve result and provided buffer and consume hasher instance.
fn finalize_fixed_into_reset(&mut self, out: &mut GenericArray<u8, Self::OutputSize>);
}

/// Trait for returning digest result with the variable size
Expand All @@ -99,7 +125,16 @@ pub trait VariableOutput: core::marker::Sized {
///
/// Closure is guaranteed to be called, length of the buffer passed to it
/// will be equal to `output_size`.
fn finalize_variable<F: FnOnce(&[u8])>(self, f: F);
#[inline]
fn finalize_variable(mut self, f: impl FnOnce(&[u8])) {
self.finalize_variable_reset(f);
}

/// Retrieve result via closure and reset hasher.
///
/// Closure is guaranteed to be called, length of the buffer passed to it
/// will be equal to `output_size`.
fn finalize_variable_reset(&mut self, f: impl FnOnce(&[u8]));

/// Retrieve result into vector and consume hasher.
#[cfg(feature = "alloc")]
Expand Down Expand Up @@ -135,7 +170,13 @@ pub trait ExtendableOutput: core::marker::Sized {
type Reader: XofReader;

/// Retrieve XOF reader and consume hasher instance.
fn finalize_xof(self) -> Self::Reader;
#[inline]
fn finalize_xof(mut self) -> Self::Reader {
self.finalize_xof_reset()
}

/// Retrieve XOF reader and reset hasher instance.
fn finalize_xof_reset(&mut self) -> Self::Reader;

/// Retrieve result into vector of specified length.
#[cfg(feature = "alloc")]
Expand All @@ -147,12 +188,6 @@ pub trait ExtendableOutput: core::marker::Sized {
}
}

/// Trait for resetting hash instances
pub trait Reset {
/// Reset hasher instance to its initial state and return current state.
fn reset(&mut self);
}

#[macro_export]
/// Implements `std::io::Write` trait for implementer of [`Update`]
macro_rules! impl_write {
Expand Down

0 comments on commit 47d5f10

Please sign in to comment.