summaryrefslogtreecommitdiffstats
path: root/third_party/rust/digest/src/digest.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/digest/src/digest.rs')
-rw-r--r--third_party/rust/digest/src/digest.rs236
1 files changed, 236 insertions, 0 deletions
diff --git a/third_party/rust/digest/src/digest.rs b/third_party/rust/digest/src/digest.rs
new file mode 100644
index 0000000000..9373550ca0
--- /dev/null
+++ b/third_party/rust/digest/src/digest.rs
@@ -0,0 +1,236 @@
+use super::{FixedOutput, FixedOutputReset, InvalidBufferSize, Reset, Update};
+use crypto_common::{typenum::Unsigned, Output, OutputSizeUser};
+
+#[cfg(feature = "alloc")]
+use alloc::boxed::Box;
+
+/// Marker trait for cryptographic hash functions.
+pub trait HashMarker {}
+
+/// Convenience wrapper trait covering functionality of cryptographic hash
+/// functions with fixed output size.
+///
+/// This trait wraps [`Update`], [`FixedOutput`], [`Default`], and
+/// [`HashMarker`] traits and provides additional convenience methods.
+pub trait Digest: OutputSizeUser {
+ /// Create new hasher instance.
+ fn new() -> Self;
+
+ /// Create new hasher instance which has processed the provided data.
+ fn new_with_prefix(data: impl AsRef<[u8]>) -> Self;
+
+ /// Process data, updating the internal state.
+ fn update(&mut self, data: impl AsRef<[u8]>);
+
+ /// Process input data in a chained manner.
+ #[must_use]
+ fn chain_update(self, data: impl AsRef<[u8]>) -> Self;
+
+ /// Retrieve result and consume hasher instance.
+ fn finalize(self) -> Output<Self>;
+
+ /// Write result into provided array and consume the hasher instance.
+ fn finalize_into(self, out: &mut Output<Self>);
+
+ /// Retrieve result and reset hasher instance.
+ fn finalize_reset(&mut self) -> Output<Self>
+ where
+ Self: FixedOutputReset;
+
+ /// Write result into provided array and reset the hasher instance.
+ fn finalize_into_reset(&mut self, out: &mut Output<Self>)
+ where
+ Self: FixedOutputReset;
+
+ /// Reset hasher instance to its initial state.
+ fn reset(&mut self)
+ where
+ Self: Reset;
+
+ /// Get output size of the hasher
+ fn output_size() -> usize;
+
+ /// Compute hash of `data`.
+ fn digest(data: impl AsRef<[u8]>) -> Output<Self>;
+}
+
+impl<D: FixedOutput + Default + Update + HashMarker> Digest for D {
+ #[inline]
+ fn new() -> Self {
+ Self::default()
+ }
+
+ #[inline]
+ fn new_with_prefix(data: impl AsRef<[u8]>) -> Self
+ where
+ Self: Default + Sized,
+ {
+ let mut h = Self::default();
+ h.update(data.as_ref());
+ h
+ }
+
+ #[inline]
+ fn update(&mut self, data: impl AsRef<[u8]>) {
+ Update::update(self, data.as_ref());
+ }
+
+ #[inline]
+ fn chain_update(mut self, data: impl AsRef<[u8]>) -> Self {
+ Update::update(&mut self, data.as_ref());
+ self
+ }
+
+ #[inline]
+ fn finalize(self) -> Output<Self> {
+ FixedOutput::finalize_fixed(self)
+ }
+
+ #[inline]
+ fn finalize_into(self, out: &mut Output<Self>) {
+ FixedOutput::finalize_into(self, out);
+ }
+
+ #[inline]
+ fn finalize_reset(&mut self) -> Output<Self>
+ where
+ Self: FixedOutputReset,
+ {
+ FixedOutputReset::finalize_fixed_reset(self)
+ }
+
+ #[inline]
+ fn finalize_into_reset(&mut self, out: &mut Output<Self>)
+ where
+ Self: FixedOutputReset,
+ {
+ FixedOutputReset::finalize_into_reset(self, out);
+ }
+
+ #[inline]
+ fn reset(&mut self)
+ where
+ Self: Reset,
+ {
+ Reset::reset(self)
+ }
+
+ #[inline]
+ fn output_size() -> usize {
+ Self::OutputSize::to_usize()
+ }
+
+ #[inline]
+ fn digest(data: impl AsRef<[u8]>) -> Output<Self> {
+ let mut hasher = Self::default();
+ hasher.update(data.as_ref());
+ hasher.finalize()
+ }
+}
+
+/// Modification of the [`Digest`] trait suitable for trait objects.
+pub trait DynDigest {
+ /// Digest input data.
+ ///
+ /// This method can be called repeatedly for use with streaming messages.
+ fn update(&mut self, data: &[u8]);
+
+ /// Retrieve result and reset hasher instance
+ #[cfg(feature = "alloc")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
+ fn finalize_reset(&mut self) -> Box<[u8]> {
+ let mut result = vec![0; self.output_size()];
+ self.finalize_into_reset(&mut result).unwrap();
+ result.into_boxed_slice()
+ }
+
+ /// Retrieve result and consume boxed hasher instance
+ #[cfg(feature = "alloc")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
+ #[allow(clippy::boxed_local)]
+ fn finalize(mut self: Box<Self>) -> Box<[u8]> {
+ let mut result = vec![0; self.output_size()];
+ self.finalize_into_reset(&mut result).unwrap();
+ result.into_boxed_slice()
+ }
+
+ /// Write result into provided array and consume the hasher instance.
+ ///
+ /// Returns error if buffer length is not equal to `output_size`.
+ fn finalize_into(self, buf: &mut [u8]) -> Result<(), InvalidBufferSize>;
+
+ /// Write result into provided array and reset the hasher instance.
+ ///
+ /// Returns error if buffer length is not equal to `output_size`.
+ fn finalize_into_reset(&mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize>;
+
+ /// 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
+ #[cfg(feature = "alloc")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
+ fn box_clone(&self) -> Box<dyn DynDigest>;
+}
+
+impl<D: Update + FixedOutputReset + Reset + Clone + 'static> DynDigest for D {
+ fn update(&mut self, data: &[u8]) {
+ Update::update(self, data);
+ }
+
+ #[cfg(feature = "alloc")]
+ fn finalize_reset(&mut self) -> Box<[u8]> {
+ FixedOutputReset::finalize_fixed_reset(self)
+ .to_vec()
+ .into_boxed_slice()
+ }
+
+ #[cfg(feature = "alloc")]
+ fn finalize(self: Box<Self>) -> Box<[u8]> {
+ FixedOutput::finalize_fixed(*self)
+ .to_vec()
+ .into_boxed_slice()
+ }
+
+ fn finalize_into(self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> {
+ if buf.len() == self.output_size() {
+ FixedOutput::finalize_into(self, Output::<Self>::from_mut_slice(buf));
+ Ok(())
+ } else {
+ Err(InvalidBufferSize)
+ }
+ }
+
+ fn finalize_into_reset(&mut self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> {
+ if buf.len() == self.output_size() {
+ FixedOutputReset::finalize_into_reset(self, Output::<Self>::from_mut_slice(buf));
+ Ok(())
+ } else {
+ Err(InvalidBufferSize)
+ }
+ }
+
+ fn reset(&mut self) {
+ Reset::reset(self);
+ }
+
+ fn output_size(&self) -> usize {
+ <Self as OutputSizeUser>::OutputSize::to_usize()
+ }
+
+ #[cfg(feature = "alloc")]
+ fn box_clone(&self) -> Box<dyn DynDigest> {
+ Box::new(self.clone())
+ }
+}
+
+#[cfg(feature = "alloc")]
+#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
+impl Clone for Box<dyn DynDigest> {
+ fn clone(&self) -> Self {
+ self.box_clone()
+ }
+}