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(())
}
}
Messung V0.5 in Prozent C=82 H=92 G=86
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-18)
¤
*© Formatika GbR, Deutschland