summaryrefslogtreecommitdiffstats
path: root/vendor/digest/src/core_api/rt_variable.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/digest/src/core_api/rt_variable.rs')
-rw-r--r--vendor/digest/src/core_api/rt_variable.rs166
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(())
+ }
+}