diff options
Diffstat (limited to 'vendor/digest/src/core_api/rt_variable.rs')
-rw-r--r-- | vendor/digest/src/core_api/rt_variable.rs | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/vendor/digest/src/core_api/rt_variable.rs b/vendor/digest/src/core_api/rt_variable.rs new file mode 100644 index 000000000..3dae748f5 --- /dev/null +++ b/vendor/digest/src/core_api/rt_variable.rs @@ -0,0 +1,166 @@ +use super::{AlgorithmName, TruncSide, UpdateCore, VariableOutputCore}; +#[cfg(feature = "mac")] +use crate::MacMarker; +use crate::{HashMarker, InvalidBufferSize}; +use crate::{InvalidOutputSize, Reset, Update, VariableOutput, VariableOutputReset}; +use block_buffer::BlockBuffer; +use core::fmt; +use crypto_common::typenum::{IsLess, Le, NonZero, Unsigned, U256}; + +/// Wrapper around [`VariableOutputCore`] which selects output size +/// at run time. +#[derive(Clone)] +pub struct RtVariableCoreWrapper<T> +where + T: VariableOutputCore + UpdateCore, + T::BlockSize: IsLess<U256>, + Le<T::BlockSize, U256>: NonZero, +{ + core: T, + buffer: BlockBuffer<T::BlockSize, T::BufferKind>, + output_size: usize, +} + +impl<T> RtVariableCoreWrapper<T> +where + T: VariableOutputCore, + T::BlockSize: IsLess<U256>, + Le<T::BlockSize, U256>: NonZero, +{ + #[inline] + fn finalize_dirty(&mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize> { + let Self { + core, + buffer, + output_size, + } = self; + if out.len() != *output_size || out.len() > Self::MAX_OUTPUT_SIZE { + return Err(InvalidBufferSize); + } + let mut full_res = Default::default(); + core.finalize_variable_core(buffer, &mut full_res); + let n = out.len(); + let m = full_res.len() - n; + match T::TRUNC_SIDE { + TruncSide::Left => out.copy_from_slice(&full_res[..n]), + TruncSide::Right => out.copy_from_slice(&full_res[m..]), + } + Ok(()) + } +} + +impl<T> HashMarker for RtVariableCoreWrapper<T> +where + T: VariableOutputCore + HashMarker, + T::BlockSize: IsLess<U256>, + Le<T::BlockSize, U256>: NonZero, +{ +} + +#[cfg(feature = "mac")] +#[cfg_attr(docsrs, doc(cfg(feature = "mac")))] +impl<T> MacMarker for RtVariableCoreWrapper<T> +where + T: VariableOutputCore + MacMarker, + T::BlockSize: IsLess<U256>, + Le<T::BlockSize, U256>: NonZero, +{ +} + +impl<T> Reset for RtVariableCoreWrapper<T> +where + T: VariableOutputCore + UpdateCore + Reset, + T::BlockSize: IsLess<U256>, + Le<T::BlockSize, U256>: NonZero, +{ + #[inline] + fn reset(&mut self) { + self.buffer.reset(); + self.core.reset(); + } +} + +impl<T> Update for RtVariableCoreWrapper<T> +where + T: VariableOutputCore + UpdateCore, + T::BlockSize: IsLess<U256>, + Le<T::BlockSize, U256>: NonZero, +{ + #[inline] + fn update(&mut self, input: &[u8]) { + let Self { core, buffer, .. } = self; + buffer.digest_blocks(input, |blocks| core.update_blocks(blocks)); + } +} + +impl<T> VariableOutput for RtVariableCoreWrapper<T> +where + T: VariableOutputCore + UpdateCore, + T::BlockSize: IsLess<U256>, + Le<T::BlockSize, U256>: NonZero, +{ + const MAX_OUTPUT_SIZE: usize = T::OutputSize::USIZE; + + fn new(output_size: usize) -> Result<Self, InvalidOutputSize> { + let buffer = Default::default(); + T::new(output_size).map(|core| Self { + core, + buffer, + output_size, + }) + } + + fn output_size(&self) -> usize { + self.output_size + } + + fn finalize_variable(mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize> { + self.finalize_dirty(out) + } +} + +impl<T> VariableOutputReset for RtVariableCoreWrapper<T> +where + T: VariableOutputCore + UpdateCore + Reset, + T::BlockSize: IsLess<U256>, + Le<T::BlockSize, U256>: NonZero, +{ + fn finalize_variable_reset(&mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize> { + self.finalize_dirty(out)?; + self.core.reset(); + self.buffer.reset(); + Ok(()) + } +} + +impl<T> fmt::Debug for RtVariableCoreWrapper<T> +where + T: VariableOutputCore + UpdateCore + AlgorithmName, + T::BlockSize: IsLess<U256>, + Le<T::BlockSize, U256>: NonZero, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + T::write_alg_name(f)?; + f.write_str(" { .. }") + } +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl<T> std::io::Write for RtVariableCoreWrapper<T> +where + T: VariableOutputCore + UpdateCore, + T::BlockSize: IsLess<U256>, + Le<T::BlockSize, U256>: NonZero, +{ + #[inline] + fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { + Update::update(self, buf); + Ok(buf.len()) + } + + #[inline] + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} |