1use core::{fmt, mem};
4use digest::{
5 core_api::BlockSizeUser,
6 generic_array::{typenum::*, GenericArray},
7 FixedOutput, FixedOutputReset, OutputSizeUser, Reset, Update,
8};
9use ring::digest::Context;
10
11macro_rules! impl_digest {
12 (
13 $(#[doc = $doc:tt])*
14 $name:ident, $hasher:ident, $block_len:ty, $output_size:ty
15 ) => {
16 $(#[doc = $doc])*
17 #[repr(transparent)]
18 #[derive(Clone)]
19 pub struct $name(Context);
20
21 impl $name {
22 fn take(&mut self) -> Context {
23 mem::replace(&mut self.0, Context::new(&ring::digest::$hasher))
24 }
25 }
26
27 impl Default for $name {
28 fn default() -> Self {
29 $name(Context::new(&ring::digest::$hasher))
30 }
31 }
32
33 impl Update for $name {
34 fn update(&mut self, data: &[u8]) {
35 self.0.update(data.as_ref())
36 }
37 }
38
39 impl BlockSizeUser for $name {
40 type BlockSize = $block_len;
41 }
42
43 impl OutputSizeUser for $name {
44 type OutputSize = $output_size;
45 }
46
47 impl FixedOutput for $name {
48 fn finalize_into(self, out: &mut GenericArray<u8, Self::OutputSize>) {
49 *out = GenericArray::clone_from_slice(self.0.finish().as_ref());
50 }
51 }
52
53 impl FixedOutputReset for $name {
54 fn finalize_into_reset(&mut self, out: &mut GenericArray<u8, Self::OutputSize>) {
55 *out = GenericArray::clone_from_slice(self.take().finish().as_ref());
56 }
57 }
58
59 impl Reset for $name {
60 fn reset(&mut self) {
61 self.take();
62 }
63 }
64
65 impl fmt::Debug for $name {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 f.debug_struct(stringify!($name)).finish_non_exhaustive()
68 }
69 }
70 };
71}
72
73impl_digest!(
74 Sha1,
76 SHA1_FOR_LEGACY_USE_ONLY,
77 U64,
78 U20
79);
80
81impl_digest!(
82 Sha256,
84 SHA256,
85 U64,
86 U32
87);
88
89impl_digest!(
90 Sha384,
92 SHA384,
93 U128,
94 U48
95);
96
97impl_digest!(
98 Sha512,
100 SHA512,
101 U128,
102 U64
103);
104
105impl_digest!(
106 Sha512Trunc256,
108 SHA512_256,
109 U128,
110 U32
111);