Coverage Report

Created: 2025-06-24 07:03

/rust/registry/src/index.crates.io-6f17d22bba15001f/digest-0.10.7/src/digest.rs
Line
Count
Source (jump to first uncovered line)
1
use super::{FixedOutput, FixedOutputReset, InvalidBufferSize, Reset, Update};
2
use crypto_common::{typenum::Unsigned, Output, OutputSizeUser};
3
4
#[cfg(feature = "alloc")]
5
use alloc::boxed::Box;
6
7
/// Marker trait for cryptographic hash functions.
8
pub trait HashMarker {}
9
10
/// Convenience wrapper trait covering functionality of cryptographic hash
11
/// functions with fixed output size.
12
///
13
/// This trait wraps [`Update`], [`FixedOutput`], [`Default`], and
14
/// [`HashMarker`] traits and provides additional convenience methods.
15
pub trait Digest: OutputSizeUser {
16
    /// Create new hasher instance.
17
    fn new() -> Self;
18
19
    /// Create new hasher instance which has processed the provided data.
20
    fn new_with_prefix(data: impl AsRef<[u8]>) -> Self;
21
22
    /// Process data, updating the internal state.
23
    fn update(&mut self, data: impl AsRef<[u8]>);
24
25
    /// Process input data in a chained manner.
26
    #[must_use]
27
    fn chain_update(self, data: impl AsRef<[u8]>) -> Self;
28
29
    /// Retrieve result and consume hasher instance.
30
    fn finalize(self) -> Output<Self>;
31
32
    /// Write result into provided array and consume the hasher instance.
33
    fn finalize_into(self, out: &mut Output<Self>);
34
35
    /// Retrieve result and reset hasher instance.
36
    fn finalize_reset(&mut self) -> Output<Self>
37
    where
38
        Self: FixedOutputReset;
39
40
    /// Write result into provided array and reset the hasher instance.
41
    fn finalize_into_reset(&mut self, out: &mut Output<Self>)
42
    where
43
        Self: FixedOutputReset;
44
45
    /// Reset hasher instance to its initial state.
46
    fn reset(&mut self)
47
    where
48
        Self: Reset;
49
50
    /// Get output size of the hasher
51
    fn output_size() -> usize;
52
53
    /// Compute hash of `data`.
54
    fn digest(data: impl AsRef<[u8]>) -> Output<Self>;
55
}
56
57
impl<D: FixedOutput + Default + Update + HashMarker> Digest for D {
58
    #[inline]
59
    fn new() -> Self {
60
        Self::default()
61
    }
62
63
    #[inline]
64
    fn new_with_prefix(data: impl AsRef<[u8]>) -> Self
65
    where
66
        Self: Default + Sized,
67
    {
68
        let mut h = Self::default();
69
        h.update(data.as_ref());
70
        h
71
    }
72
73
    #[inline]
74
0
    fn update(&mut self, data: impl AsRef<[u8]>) {
75
0
        Update::update(self, data.as_ref());
76
0
    }
77
78
    #[inline]
79
    fn chain_update(mut self, data: impl AsRef<[u8]>) -> Self {
80
        Update::update(&mut self, data.as_ref());
81
        self
82
    }
83
84
    #[inline]
85
0
    fn finalize(self) -> Output<Self> {
86
0
        FixedOutput::finalize_fixed(self)
87
0
    }
88
89
    #[inline]
90
    fn finalize_into(self, out: &mut Output<Self>) {
91
        FixedOutput::finalize_into(self, out);
92
    }
93
94
    #[inline]
95
    fn finalize_reset(&mut self) -> Output<Self>
96
    where
97
        Self: FixedOutputReset,
98
    {
99
        FixedOutputReset::finalize_fixed_reset(self)
100
    }
101
102
    #[inline]
103
    fn finalize_into_reset(&mut self, out: &mut Output<Self>)
104
    where
105
        Self: FixedOutputReset,
106
    {
107
        FixedOutputReset::finalize_into_reset(self, out);
108
    }
109
110
    #[inline]
111
    fn reset(&mut self)
112
    where
113
        Self: Reset,
114
    {
115
        Reset::reset(self)
116
    }
117
118
    #[inline]
119
    fn output_size() -> usize {
120
        Self::OutputSize::to_usize()
121
    }
122
123
    #[inline]
124
    fn digest(data: impl AsRef<[u8]>) -> Output<Self> {
125
        let mut hasher = Self::default();
126
        hasher.update(data.as_ref());
127
        hasher.finalize()
128
    }
129
}
130
131
/// Modification of the [`Digest`] trait suitable for trait objects.
132
pub trait DynDigest {
133
    /// Digest input data.
134
    ///
135
    /// This method can be called repeatedly for use with streaming messages.
136
    fn update(&mut self, data: &[u8]);
137
138
    /// Retrieve result and reset hasher instance
139
    #[cfg(feature = "alloc")]
140
    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
141
    fn finalize_reset(&mut self) -> Box<[u8]> {
142
        let mut result = vec![0; self.output_size()];
143
        self.finalize_into_reset(&mut result).unwrap();
144
        result.into_boxed_slice()
145
    }
146
147
    /// Retrieve result and consume boxed hasher instance
148
    #[cfg(feature = "alloc")]
149
    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
150
    #[allow(clippy::boxed_local)]
151
    fn finalize(mut self: Box<Self>) -> Box<[u8]> {
152
        let mut result = vec![0; self.output_size()];
153
        self.finalize_into_reset(&mut result).unwrap();
154
        result.into_boxed_slice()
155
    }
156
157
    /// Write result into provided array and consume the hasher instance.
158
    ///
159
    /// Returns error if buffer length is not equal to `output_size`.
160
    fn finalize_into(self, buf: &mut [u8]) -> Result<(), InvalidBufferSize>;
161
162
    /// Write result into provided array and reset the hasher instance.
163
    ///
164
    /// Returns error if buffer length is not equal to `output_size`.
165
    fn finalize_into_reset(&mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize>;
166
167
    /// Reset hasher instance to its initial state.
168
    fn reset(&mut self);
169
170
    /// Get output size of the hasher
171
    fn output_size(&self) -> usize;
172
173
    /// Clone hasher state into a boxed trait object
174
    #[cfg(feature = "alloc")]
175
    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
176
    fn box_clone(&self) -> Box<dyn DynDigest>;
177
}
178
179
impl<D: Update + FixedOutputReset + Reset + Clone + 'static> DynDigest for D {
180
    fn update(&mut self, data: &[u8]) {
181
        Update::update(self, data);
182
    }
183
184
    #[cfg(feature = "alloc")]
185
    fn finalize_reset(&mut self) -> Box<[u8]> {
186
        FixedOutputReset::finalize_fixed_reset(self)
187
            .to_vec()
188
            .into_boxed_slice()
189
    }
190
191
    #[cfg(feature = "alloc")]
192
    fn finalize(self: Box<Self>) -> Box<[u8]> {
193
        FixedOutput::finalize_fixed(*self)
194
            .to_vec()
195
            .into_boxed_slice()
196
    }
197
198
    fn finalize_into(self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> {
199
        if buf.len() == self.output_size() {
200
            FixedOutput::finalize_into(self, Output::<Self>::from_mut_slice(buf));
201
            Ok(())
202
        } else {
203
            Err(InvalidBufferSize)
204
        }
205
    }
206
207
    fn finalize_into_reset(&mut self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> {
208
        if buf.len() == self.output_size() {
209
            FixedOutputReset::finalize_into_reset(self, Output::<Self>::from_mut_slice(buf));
210
            Ok(())
211
        } else {
212
            Err(InvalidBufferSize)
213
        }
214
    }
215
216
    fn reset(&mut self) {
217
        Reset::reset(self);
218
    }
219
220
    fn output_size(&self) -> usize {
221
        <Self as OutputSizeUser>::OutputSize::to_usize()
222
    }
223
224
    #[cfg(feature = "alloc")]
225
    fn box_clone(&self) -> Box<dyn DynDigest> {
226
        Box::new(self.clone())
227
    }
228
}
229
230
#[cfg(feature = "alloc")]
231
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
232
impl Clone for Box<dyn DynDigest> {
233
    fn clone(&self) -> Self {
234
        self.box_clone()
235
    }
236
}