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 = "const-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 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 fn finalize_into(self, buf: &mut [u8]) -> Result<(), InvalidBufferSize>;
161
162 fn finalize_into_reset(&mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize>;
166
167 fn reset(&mut self);
169
170 fn output_size(&self) -> usize;
172
173 #[cfg(feature = "alloc")]
175 fn box_clone(&self) -> Box<dyn DynDigest>;
176}
177
178impl<D: Update + FixedOutputReset + Reset + Clone + 'static> DynDigest for D {
179 fn update(&mut self, data: &[u8]) {
180 Update::update(self, data);
181 }
182
183 #[cfg(feature = "alloc")]
184 fn finalize_reset(&mut self) -> Box<[u8]> {
185 FixedOutputReset::finalize_fixed_reset(self)
186 .to_vec()
187 .into_boxed_slice()
188 }
189
190 #[cfg(feature = "alloc")]
191 fn finalize(self: Box<Self>) -> Box<[u8]> {
192 FixedOutput::finalize_fixed(*self)
193 .to_vec()
194 .into_boxed_slice()
195 }
196
197 fn finalize_into(self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> {
198 buf.try_into()
199 .map_err(|_| InvalidBufferSize)
200 .map(|buf| FixedOutput::finalize_into(self, buf))
201 }
202
203 fn finalize_into_reset(&mut self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> {
204 let buf = <&mut Output<Self>>::try_from(buf).map_err(|_| InvalidBufferSize)?;
205 FixedOutputReset::finalize_into_reset(self, buf);
206 Ok(())
207 }
208
209 fn reset(&mut self) {
210 Reset::reset(self);
211 }
212
213 fn output_size(&self) -> usize {
214 <Self as OutputSizeUser>::OutputSize::to_usize()
215 }
216
217 #[cfg(feature = "alloc")]
218 fn box_clone(&self) -> Box<dyn DynDigest> {
219 Box::new(self.clone())
220 }
221}
222
223#[cfg(feature = "alloc")]
224impl Clone for Box<dyn DynDigest> {
225 fn clone(&self) -> Self {
226 self.box_clone()
227 }
228}
229
230#[cfg(feature = "const-oid")]
232pub trait DynDigestWithOid: DynDigest + DynAssociatedOid {}
233
234#[cfg(feature = "const-oid")]
235impl<T: DynDigest + DynAssociatedOid> DynDigestWithOid for T {}