1use super::{FixedOutput, FixedOutputReset, InvalidBufferSize, Reset, Update};
2use common::{Output, OutputSizeUser, typenum::Unsigned};
3
4#[cfg(feature = "alloc")]
5use alloc::boxed::Box;
6#[cfg(feature = "oid")]
7use const_oid::DynAssociatedOid;
8
9pub trait HashMarker {}
11
12pub trait Digest: OutputSizeUser {
18 fn new() -> Self;
20
21 fn new_with_prefix(data: impl AsRef<[u8]>) -> Self;
23
24 fn update(&mut self, data: impl AsRef<[u8]>);
26
27 #[must_use]
29 fn chain_update(self, data: impl AsRef<[u8]>) -> Self;
30
31 fn finalize(self) -> Output<Self>;
33
34 fn finalize_into(self, out: &mut Output<Self>);
36
37 fn finalize_reset(&mut self) -> Output<Self>
39 where
40 Self: FixedOutputReset;
41
42 fn finalize_into_reset(&mut self, out: &mut Output<Self>)
44 where
45 Self: FixedOutputReset;
46
47 fn reset(&mut self)
49 where
50 Self: Reset;
51
52 fn output_size() -> usize;
54
55 fn digest(data: impl AsRef<[u8]>) -> Output<Self>;
57}
58
59impl<D: FixedOutput + Default + Update + HashMarker> Digest for D {
60 #[inline]
61 fn new() -> Self {
62 Self::default()
63 }
64
65 #[inline]
66 fn new_with_prefix(data: impl AsRef<[u8]>) -> Self
67 where
68 Self: Default + Sized,
69 {
70 let mut h = Self::default();
71 h.update(data.as_ref());
72 h
73 }
74
75 #[inline]
76 fn update(&mut self, data: impl AsRef<[u8]>) {
77 Update::update(self, data.as_ref());
78 }
79
80 #[inline]
81 fn chain_update(mut self, data: impl AsRef<[u8]>) -> Self {
82 Update::update(&mut self, data.as_ref());
83 self
84 }
85
86 #[inline]
87 fn finalize(self) -> Output<Self> {
88 FixedOutput::finalize_fixed(self)
89 }
90
91 #[inline]
92 fn finalize_into(self, out: &mut Output<Self>) {
93 FixedOutput::finalize_into(self, out);
94 }
95
96 #[inline]
97 fn finalize_reset(&mut self) -> Output<Self>
98 where
99 Self: FixedOutputReset,
100 {
101 FixedOutputReset::finalize_fixed_reset(self)
102 }
103
104 #[inline]
105 fn finalize_into_reset(&mut self, out: &mut Output<Self>)
106 where
107 Self: FixedOutputReset,
108 {
109 FixedOutputReset::finalize_into_reset(self, out);
110 }
111
112 #[inline]
113 fn reset(&mut self)
114 where
115 Self: Reset,
116 {
117 Reset::reset(self);
118 }
119
120 #[inline]
121 fn output_size() -> usize {
122 Self::OutputSize::to_usize()
123 }
124
125 #[inline]
126 fn digest(data: impl AsRef<[u8]>) -> Output<Self> {
127 let mut hasher = Self::default();
128 hasher.update(data.as_ref());
129 hasher.finalize()
130 }
131}
132
133pub trait DynDigest {
135 fn update(&mut self, data: &[u8]);
139
140 #[cfg(feature = "alloc")]
142 fn finalize_reset(&mut self) -> Box<[u8]> {
143 let mut result = vec![0; self.output_size()];
144 self.finalize_into_reset(&mut result).unwrap();
145 result.into_boxed_slice()
146 }
147
148 #[cfg(feature = "alloc")]
150 #[allow(clippy::boxed_local)]
151 #[must_use]
152 fn finalize(mut self: Box<Self>) -> Box<[u8]> {
153 let mut result = vec![0; self.output_size()];
154 self.finalize_into_reset(&mut result).unwrap();
155 result.into_boxed_slice()
156 }
157
158 fn finalize_into(self, buf: &mut [u8]) -> Result<(), InvalidBufferSize>;
163
164 fn finalize_into_reset(&mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize>;
169
170 fn reset(&mut self);
172
173 fn output_size(&self) -> usize;
175
176 #[cfg(feature = "alloc")]
178 fn box_clone(&self) -> Box<dyn DynDigest>;
179}
180
181impl<D: Update + FixedOutputReset + Reset + Clone + 'static> DynDigest for D {
182 fn update(&mut self, data: &[u8]) {
183 Update::update(self, data);
184 }
185
186 #[cfg(feature = "alloc")]
187 fn finalize_reset(&mut self) -> Box<[u8]> {
188 FixedOutputReset::finalize_fixed_reset(self)
189 .to_vec()
190 .into_boxed_slice()
191 }
192
193 #[cfg(feature = "alloc")]
194 fn finalize(self: Box<Self>) -> Box<[u8]> {
195 FixedOutput::finalize_fixed(*self)
196 .to_vec()
197 .into_boxed_slice()
198 }
199
200 fn finalize_into(self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> {
201 buf.try_into()
202 .map_err(|_| InvalidBufferSize)
203 .map(|buf| FixedOutput::finalize_into(self, buf))
204 }
205
206 fn finalize_into_reset(&mut self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> {
207 let buf = <&mut Output<Self>>::try_from(buf).map_err(|_| InvalidBufferSize)?;
208 FixedOutputReset::finalize_into_reset(self, buf);
209 Ok(())
210 }
211
212 fn reset(&mut self) {
213 Reset::reset(self);
214 }
215
216 fn output_size(&self) -> usize {
217 <Self as OutputSizeUser>::OutputSize::to_usize()
218 }
219
220 #[cfg(feature = "alloc")]
221 fn box_clone(&self) -> Box<dyn DynDigest> {
222 Box::new(self.clone())
223 }
224}
225
226#[cfg(feature = "alloc")]
227impl Clone for Box<dyn DynDigest> {
228 fn clone(&self) -> Self {
229 self.box_clone()
230 }
231}
232
233#[cfg(feature = "oid")]
235pub trait DynDigestWithOid: DynDigest + DynAssociatedOid {}
236
237#[cfg(feature = "oid")]
238impl<T: DynDigest + DynAssociatedOid> DynDigestWithOid for T {}