use super::{ AlgorithmName, Buffer, BufferKindUser, FixedOutputCore, Reset, TruncSide, UpdateCore, VariableOutputCore, }; use crate::HashMarker; #[cfg(feature = "mac")] use crate::MacMarker; use core::{fmt, marker::PhantomData}; use crypto_common::{ generic_array::{ArrayLength, GenericArray}, typenum::{IsLess, IsLessOrEqual, Le, LeEq, NonZero, U256}, Block, BlockSizeUser, OutputSizeUser, }; /// Wrapper around [`VariableOutputCore`] which selects output size /// at compile time. #[derive(Clone)] pub struct CtVariableCoreWrapper where T: VariableOutputCore, OutSize: ArrayLength + IsLessOrEqual, LeEq: NonZero, T::BlockSize: IsLess, Le: NonZero, { inner: T, _out: PhantomData, } impl HashMarker for CtVariableCoreWrapper where T: VariableOutputCore + HashMarker, OutSize: ArrayLength + IsLessOrEqual, LeEq: NonZero, T::BlockSize: IsLess, Le: NonZero, { } #[cfg(feature = "mac")] impl MacMarker for CtVariableCoreWrapper where T: VariableOutputCore + MacMarker, OutSize: ArrayLength + IsLessOrEqual, LeEq: NonZero, T::BlockSize: IsLess, Le: NonZero, { } impl BlockSizeUser for CtVariableCoreWrapper where T: VariableOutputCore, OutSize: ArrayLength + IsLessOrEqual, LeEq: NonZero, T::BlockSize: IsLess, Le: NonZero, { type BlockSize = T::BlockSize; } impl UpdateCore for CtVariableCoreWrapper where T: VariableOutputCore, OutSize: ArrayLength + IsLessOrEqual, LeEq: NonZero, T::BlockSize: IsLess, Le: NonZero, { #[inline] fn update_blocks(&mut self, blocks: &[Block]) { self.inner.update_blocks(blocks); } } impl OutputSizeUser for CtVariableCoreWrapper where T: VariableOutputCore, OutSize: ArrayLength + IsLessOrEqual + 'static, LeEq: NonZero, T::BlockSize: IsLess, Le: NonZero, { type OutputSize = OutSize; } impl BufferKindUser for CtVariableCoreWrapper where T: VariableOutputCore, OutSize: ArrayLength + IsLessOrEqual, LeEq: NonZero, T::BlockSize: IsLess, Le: NonZero, { type BufferKind = T::BufferKind; } impl FixedOutputCore for CtVariableCoreWrapper where T: VariableOutputCore, OutSize: ArrayLength + IsLessOrEqual + 'static, LeEq: NonZero, T::BlockSize: IsLess, Le: NonZero, { #[inline] fn finalize_fixed_core( &mut self, buffer: &mut Buffer, out: &mut GenericArray, ) { let mut full_res = Default::default(); self.inner.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..]), } } } impl Default for CtVariableCoreWrapper where T: VariableOutputCore, OutSize: ArrayLength + IsLessOrEqual, LeEq: NonZero, T::BlockSize: IsLess, Le: NonZero, { #[inline] fn default() -> Self { Self { inner: T::new(OutSize::USIZE).unwrap(), _out: PhantomData, } } } impl Reset for CtVariableCoreWrapper where T: VariableOutputCore, OutSize: ArrayLength + IsLessOrEqual, LeEq: NonZero, T::BlockSize: IsLess, Le: NonZero, { #[inline] fn reset(&mut self) { *self = Default::default(); } } impl AlgorithmName for CtVariableCoreWrapper where T: VariableOutputCore + AlgorithmName, OutSize: ArrayLength + IsLessOrEqual, LeEq: NonZero, T::BlockSize: IsLess, Le: NonZero, { fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { T::write_alg_name(f)?; f.write_str("_")?; write!(f, "{}", OutSize::USIZE) } }