1use core::fmt;
2
3use digest::block_api::{
4 AlgorithmName,
5 BlockSizeUser,
6 ExtendableOutputCore,
7 Reset,
8 UpdateCore,
9 XofReaderCore,
10};
11use digest::block_buffer::{
12 EagerBuffer,
13 ReadBuffer,
14};
15use digest::consts::{
16 U0,
17 U136,
18 U168,
19};
20use digest::{
21 CollisionResistance,
22 ExtendableOutput,
23 ExtendableOutputReset,
24 HashMarker,
25 Update,
26 XofReader,
27};
28
29use crate::internal_block_api::{
30 Sha3HasherCore,
31 Sha3ReaderCore,
32};
33use crate::{
34 DEFAULT_ROUND_COUNT,
35 SHAKE_PAD,
36};
37
38macro_rules! impl_shake {
39 (
40 $name:ident, $reader_name:ident, $rate:ty, $alg_name:expr
41 ) => {
42 #[doc = $alg_name]
43 #[doc = " hasher."]
44 #[derive(Clone)]
45 pub struct $name {
46 core: Sha3HasherCore<$rate, U0, SHAKE_PAD, DEFAULT_ROUND_COUNT>,
47 buffer: EagerBuffer<$rate>,
48 }
49
50 impl Default for $name {
51 #[inline]
52 fn default() -> Self {
53 Self {
54 core: Default::default(),
55 buffer: Default::default(),
56 }
57 }
58 }
59
60 impl HashMarker for $name {}
61
62 impl BlockSizeUser for $name {
63 type BlockSize = $rate;
64 }
65
66 impl Update for $name {
67 #[inline]
68 fn update(&mut self, data: &[u8]) {
69 let Self { core, buffer } = self;
70 buffer.digest_blocks(data, |blocks| core.update_blocks(blocks));
71 }
72 }
73
74 impl ExtendableOutput for $name {
75 type Reader = $reader_name;
76
77 #[inline]
78 fn finalize_xof(mut self) -> Self::Reader {
79 let Self { core, buffer } = &mut self;
80 let core = core.finalize_xof_core(buffer);
81 let buffer = Default::default();
82 Self::Reader { core, buffer }
83 }
84 }
85
86 impl ExtendableOutputReset for $name {
87 #[inline]
88 fn finalize_xof_reset(&mut self) -> Self::Reader {
89 let Self { core, buffer } = self;
90 let core = core.finalize_xof_core(buffer);
91 self.reset();
92 let buffer = Default::default();
93 Self::Reader { core, buffer }
94 }
95 }
96
97 impl Reset for $name {
98 #[inline]
99 fn reset(&mut self) {
100 *self = Default::default();
101 }
102 }
103
104 impl AlgorithmName for $name {
105 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 f.write_str($alg_name)
107 }
108 }
109
110 impl fmt::Debug for $name {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 f.write_str(concat!(stringify!($name), " { ... }"))
113 }
114 }
115
116 #[cfg(feature = "zeroize")]
117 impl digest::zeroize::ZeroizeOnDrop for $name {}
118
119 #[doc = $alg_name]
120 #[doc = " XOF reader."]
121 #[derive(Clone)]
122 pub struct $reader_name {
123 core: Sha3ReaderCore<$rate, DEFAULT_ROUND_COUNT>,
124 buffer: ReadBuffer<$rate>,
125 }
126
127 impl XofReader for $reader_name {
128 #[inline]
129 fn read(&mut self, buf: &mut [u8]) {
130 let Self { core, buffer } = self;
131 buffer.read(buf, |block| {
132 *block = core.read_block();
133 });
134 }
135 }
136
137 impl fmt::Debug for $reader_name {
138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139 f.write_str(concat!(stringify!($reader_name), " { ... }"))
140 }
141 }
142 };
143}
144
145impl_shake!(Shake128, Shake128Reader, U168, "SHAKE128");
146impl_shake!(Shake256, Shake256Reader, U136, "SHAKE256");
147
148impl CollisionResistance for Shake128 {
149 type CollisionResistance = U168;
151}
152
153impl CollisionResistance for Shake256 {
154 type CollisionResistance = U136;
156}