Skip to main content
This is unreleased documentation for the main (development) branch of crypto-glue.

digest/buffer_macros/
xof.rs

1/// Creates a buffered wrapper around block-level "core" type which implements extendable output size traits.
2#[macro_export]
3macro_rules! buffer_xof {
4    (
5        $(#[$hasher_attr:meta])*
6        $hasher_vis:vis struct $hasher_name:ident($hasher_core:ty);
7        $(oid: $oid:literal;)?
8        impl: $($hasher_trait_name:ident)*;
9
10        $(#[$reader_attr:meta])*
11        $reader_vis:vis struct $reader_name:ident($reader_core:ty);
12        impl: $($reader_trait_name:ident)*;
13    ) => {
14        $(#[$hasher_attr])*
15        $hasher_vis struct $hasher_name {
16            core: $hasher_core,
17            buffer: $crate::block_api::Buffer<$hasher_core>,
18        }
19
20        impl $crate::ExtendableOutput for $hasher_name {
21            type Reader = $reader_name;
22
23            #[inline]
24            fn finalize_xof(mut self) -> Self::Reader {
25                let Self { core, buffer } = &mut self;
26                let core = <$hasher_core as $crate::block_api::ExtendableOutputCore>::finalize_xof_core(core, buffer);
27                let buffer = Default::default();
28                Self::Reader { core, buffer }
29            }
30        }
31
32        $(
33            #[cfg(feature = "oid")]
34            impl $crate::const_oid::AssociatedOid for $hasher_name {
35                const OID: $crate::const_oid::ObjectIdentifier =
36                    $crate::const_oid::ObjectIdentifier::new_unwrap($oid);
37            }
38        )?
39
40        $crate::buffer_xof!(
41            impl_inner: $hasher_name($hasher_core);
42            $($hasher_trait_name)*;
43        );
44
45        $(#[$reader_attr])*
46        $reader_vis struct $reader_name {
47            core: $reader_core,
48            buffer: $crate::block_buffer::ReadBuffer<<$reader_core as $crate::block_api::BlockSizeUser>::BlockSize>,
49        }
50
51        impl $crate::XofReader for $reader_name {
52            #[inline]
53            fn read(&mut self, buf: &mut [u8]) {
54                let Self { core, buffer } = self;
55                buffer.read(buf, |block| {
56                    *block = $crate::block_api::XofReaderCore::read_block(core);
57                });
58            }
59        }
60
61        $crate::buffer_xof!(
62            impl_inner: $reader_name($reader_core);
63            $($reader_trait_name)*;
64        );
65    };
66
67    // Terminates `impl_inner` sequences.
68    (
69        impl_inner: $name:ident($core_ty:ty); ;
70    ) => {};
71
72    // Implements the set of traits common for XOF hashers
73    (
74        impl_inner: $name:ident($core_ty:ty);
75        XofHasherTraits $($trait_name:ident)*;
76    ) => {
77        $crate::buffer_xof!(
78            impl_inner: $name($core_ty);
79            Debug AlgorithmName Clone Default BlockSizeUser CoreProxy HashMarker Update SerializableState Reset ExtendableOutputReset $($trait_name)* ;
80        );
81    };
82
83    // Implements the set of traits common for XOF readers
84    (
85        impl_inner: $name:ident($core_ty:ty);
86        XofReaderTraits $($trait_name:ident)*;
87    ) => {
88        $crate::buffer_xof!(
89            impl_inner: $name($core_ty);
90            Debug Clone BlockSizeUser
91            $($trait_name)*;);
92    };
93
94    // Implements `Debug`
95    (
96        impl_inner: $name:ident($core_ty:ty);
97        Debug $($trait_name:ident)*;
98    ) => {
99        impl core::fmt::Debug for $name {
100            #[inline]
101            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
102                f.write_str(concat!(stringify!($name), " { ... }"))
103            }
104        }
105
106        $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;);
107    };
108
109    // Implements `AlgorithmName`
110    (
111        impl_inner: $name:ident($core_ty:ty);
112        AlgorithmName $($trait_name:ident)*;
113    ) => {
114        impl $crate::common::AlgorithmName for $name {
115            #[inline]
116            fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
117                <$core_ty as $crate::common::AlgorithmName>::write_alg_name(f)
118            }
119        }
120
121        $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;);
122    };
123
124    // Implements `Default`
125    (
126        impl_inner: $name:ident($core_ty:ty);
127        Default $($trait_name:ident)*;
128    ) => {
129        impl Default for $name {
130            #[inline]
131            fn default() -> Self {
132                Self {
133                    core: Default::default(),
134                    buffer: Default::default(),
135                }
136            }
137        }
138
139        $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;);
140    };
141
142    // Implements `CustomizedInit`
143    (
144        impl_inner: $name:ident($core_ty:ty);
145        CustomizedInit $($trait_name:ident)*;
146    ) => {
147        impl $crate::CustomizedInit for $name {
148            #[inline]
149            fn new_customized(customization: &[u8]) -> Self {
150                Self {
151                    core: $crate::CustomizedInit::new_customized(customization),
152                    buffer: Default::default(),
153                }
154            }
155        }
156
157        $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;);
158    };
159
160    // Implements `Clone`
161    (
162        impl_inner: $name:ident($core_ty:ty);
163        Clone $($trait_name:ident)*;
164    ) => {
165        impl Clone for $name {
166            #[inline]
167            fn clone(&self) -> Self {
168                Self {
169                    core: Clone::clone(&self.core),
170                    buffer: Clone::clone(&self.buffer),
171                }
172            }
173        }
174
175        $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;);
176    };
177
178    // Implements `BlockSizeUser`
179    (
180        impl_inner: $name:ident($core_ty:ty);
181        BlockSizeUser $($trait_name:ident)*;
182    ) => {
183        impl $crate::block_api::BlockSizeUser for $name {
184            type BlockSize = <$core_ty as $crate::common::BlockSizeUser>::BlockSize;
185        }
186
187        $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;);
188    };
189
190    // Implements `CoreProxy`
191    (
192        impl_inner: $name:ident($core_ty:ty);
193        CoreProxy $($trait_name:ident)*;
194    ) => {
195        impl $crate::block_api::CoreProxy for $name {
196            type Core = $core_ty;
197            fn compose(core: Self::Core, buffer: $crate::block_api::Buffer<Self::Core>) -> Self {
198                Self { core, buffer }
199            }
200            fn decompose(self) -> (Self::Core, $crate::block_api::Buffer<Self::Core>) {
201                let Self { core, buffer } = self;
202                (core, buffer)
203            }
204        }
205
206        $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;);
207    };
208
209    // Implements `HashMarker`
210    (
211        impl_inner: $name:ident($core_ty:ty);
212        HashMarker $($trait_name:ident)*;
213    ) => {
214        impl $crate::HashMarker for $name {}
215
216        // Verify that `$core_ty` implements `HashMarker`
217        const _: () = {
218            fn check(v: &$core_ty) {
219                v as &dyn $crate::HashMarker;
220            }
221        };
222
223        $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;);
224    };
225
226    // Implements `Update`
227    (
228        impl_inner: $name:ident($core_ty:ty);
229        Update $($trait_name:ident)*;
230    ) => {
231        impl $crate::Update for $name {
232            #[inline]
233            fn update(&mut self, data: &[u8]) {
234                let Self { core, buffer } = self;
235                buffer.digest_blocks(data, |blocks| {
236                    $crate::block_api::UpdateCore::update_blocks(core, blocks)
237                });
238            }
239        }
240
241        $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;);
242    };
243
244    // Implements `Reset`
245    (
246        impl_inner: $name:ident($core_ty:ty);
247        Reset $($trait_name:ident)*;
248    ) => {
249        impl $crate::Reset for $name {
250            #[inline]
251            fn reset(&mut self) {
252                $crate::Reset::reset(&mut self.core);
253                self.buffer.reset();
254            }
255        }
256
257        $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;);
258    };
259
260    // Implements `ExtendableOutputReset`
261    (
262        impl_inner: $name:ident($core_ty:ty);
263        ExtendableOutputReset $($trait_name:ident)*;
264    ) => {
265        impl $crate::ExtendableOutputReset for $name {
266            #[inline]
267            fn finalize_xof_reset(&mut self) -> Self::Reader {
268                let Self { core, buffer } = self;
269                let core = <$core_ty as $crate::block_api::ExtendableOutputCore>::finalize_xof_core(core, buffer);
270                $crate::Reset::reset(self);
271                let buffer = Default::default();
272                Self::Reader { core, buffer }
273            }
274        }
275
276        $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;);
277    };
278
279    // Implements `SerializableState`
280    (
281        impl_inner: $name:ident($core_ty:ty);
282        SerializableState $($trait_name:ident)*;
283    ) => {
284        impl $crate::common::hazmat::SerializableState for $name {
285            type SerializedStateSize = $crate::typenum::Sum<
286                <$core_ty as $crate::common::hazmat::SerializableState>::SerializedStateSize,
287                $crate::block_buffer::SerializedBufferSize<
288                    <$core_ty as $crate::block_api::BlockSizeUser>::BlockSize,
289                    <$core_ty as $crate::block_api::BufferKindUser>::BufferKind,
290                >
291            >;
292
293            #[inline]
294            fn serialize(&self) -> $crate::common::hazmat::SerializedState<Self> {
295                let serialized_core = self.core.serialize();
296                let serialized_buf = self.buffer.serialize();
297                serialized_core.concat(serialized_buf)
298            }
299
300            #[inline]
301            fn deserialize(
302                serialized_state: &$crate::common::hazmat::SerializedState<Self>,
303            ) -> Result<Self, $crate::common::hazmat::DeserializeStateError> {
304                use $crate::common::hazmat::{SerializableState, DeserializeStateError};
305
306                let (serialized_core, serialized_buf) = serialized_state
307                    .split_ref::<<$core_ty as SerializableState>::SerializedStateSize>();
308
309                let core = SerializableState::deserialize(serialized_core)?;
310                let buffer = $crate::block_buffer::BlockBuffer::deserialize(serialized_buf)
311                    .map_err(|_| DeserializeStateError)?;
312
313                Ok(Self { core, buffer })
314            }
315        }
316
317        $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;);
318    };
319}