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

digest/buffer_macros/
variable.rs

1/// Creates a buffered wrapper around block-level "core" type which implements variable output size traits
2/// with output size selected at compile time.
3#[macro_export]
4macro_rules! buffer_ct_variable {
5    (
6        $(#[$attr:meta])*
7        $vis:vis struct $name:ident<$out_size:ident>($core_ty:ty);
8        exclude: SerializableState;
9        // Ideally, we would use `$core_ty::OutputSize`, but unfortunately the compiler
10        // does not accept such code. The likely reason is this issue:
11        // https://github.com/rust-lang/rust/issues/79629
12        max_size: $max_size:ty;
13    ) => {
14        $(#[$attr])*
15        $vis struct $name<$out_size>
16        where
17            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
18        {
19            core: $crate::block_api::CtOutWrapper<$core_ty, $out_size>,
20            buffer: $crate::block_api::Buffer<$core_ty>,
21        }
22
23        impl<$out_size> core::fmt::Debug for $name<$out_size>
24        where
25            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
26        {
27            #[inline]
28            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
29                f.write_str(concat!(stringify!($name), " { ... }"))
30            }
31        }
32
33        impl<$out_size> $crate::common::AlgorithmName for $name<$out_size>
34        where
35            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
36        {
37            #[inline]
38            fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
39                <$core_ty as $crate::common::AlgorithmName>::write_alg_name(f)
40            }
41        }
42
43        impl<$out_size> Clone for $name<$out_size>
44        where
45            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
46        {
47            #[inline]
48            fn clone(&self) -> Self {
49                Self {
50                    core: Clone::clone(&self.core),
51                    buffer: Clone::clone(&self.buffer),
52                }
53            }
54        }
55
56        impl<$out_size> Default for $name<$out_size>
57        where
58            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
59        {
60            #[inline]
61            fn default() -> Self {
62                Self {
63                    core: Default::default(),
64                    buffer: Default::default(),
65                }
66            }
67        }
68
69        impl<$out_size> $crate::Reset for $name<$out_size>
70        where
71            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
72        {
73            #[inline]
74            fn reset(&mut self) {
75                $crate::Reset::reset(&mut self.core);
76                self.buffer.reset();
77            }
78        }
79
80        impl<$out_size> $crate::block_api::BlockSizeUser for $name<$out_size>
81        where
82            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
83        {
84            type BlockSize = <$core_ty as $crate::common::BlockSizeUser>::BlockSize;
85        }
86
87        impl<$out_size> $crate::OutputSizeUser for $name<$out_size>
88        where
89            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
90        {
91            type OutputSize = $out_size;
92        }
93
94        impl<$out_size> $crate::HashMarker for $name<$out_size>
95        where
96            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
97        {}
98
99        // Verify that `$wrapped_ty` implements `HashMarker`
100        const _: () = {
101            fn check<$out_size>(v: &$core_ty)
102            where
103                $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size>,
104                $crate::typenum::LeEq<$out_size, $max_size>: $crate::typenum::NonZero,
105            {
106                v as &dyn $crate::HashMarker;
107            }
108        };
109
110        impl<$out_size> $crate::block_api::CoreProxy for $name<$out_size>
111        where
112            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
113        {
114            type Core = $crate::block_api::CtOutWrapper<$core_ty, $out_size>;
115            fn compose(core: Self::Core, buffer: $crate::block_api::Buffer<Self::Core>) -> Self {
116                Self { core, buffer }
117            }
118            fn decompose(self) -> (Self::Core, $crate::block_api::Buffer<Self::Core>) {
119                let Self { core, buffer } = self;
120                (core, buffer)
121            }
122        }
123
124        impl<$out_size> $crate::Update for $name<$out_size>
125        where
126            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
127        {
128            #[inline]
129            fn update(&mut self, data: &[u8]) {
130                let Self { core, buffer } = self;
131                buffer.digest_blocks(data, |blocks| {
132                    $crate::block_api::UpdateCore::update_blocks(core, blocks)
133                });
134            }
135        }
136
137        impl<$out_size> $crate::FixedOutput for $name<$out_size>
138        where
139            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
140        {
141            #[inline]
142            fn finalize_into(mut self, out: &mut $crate::Output<Self>) {
143                let Self { core, buffer } = &mut self;
144                $crate::block_api::FixedOutputCore::finalize_fixed_core(core, buffer, out);
145            }
146        }
147
148        impl<$out_size> $crate::FixedOutputReset for $name<$out_size>
149        where
150            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
151        {
152            #[inline]
153            fn finalize_into_reset(&mut self, out: &mut $crate::Output<Self>) {
154                let Self { core, buffer } = self;
155                $crate::block_api::FixedOutputCore::finalize_fixed_core(core, buffer, out);
156                $crate::Reset::reset(self);
157            }
158        }
159    };
160    (
161        $(#[$attr:meta])*
162        $vis:vis struct $name:ident<$out_size:ident>($core_ty:ty);
163        // Ideally, we would use `$core_ty::OutputSize`, but unfortunately the compiler
164        // does not accept such code. The likely reason is this issue:
165        // https://github.com/rust-lang/rust/issues/79629
166        max_size: $max_size:ty;
167    ) => {
168        $crate::buffer_ct_variable!(
169            $(#[$attr])*
170            $vis struct $name<$out_size>($core_ty);
171            exclude: SerializableState;
172            max_size: $max_size;
173        );
174
175        impl<$out_size> $crate::common::hazmat::SerializableState for $name<$out_size>
176        where
177            $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
178        {
179            type SerializedStateSize = $crate::typenum::Sum<
180                <$core_ty as $crate::common::hazmat::SerializableState>::SerializedStateSize,
181                $crate::block_buffer::SerializedBufferSize<
182                    <$core_ty as $crate::block_api::BlockSizeUser>::BlockSize,
183                    <$core_ty as $crate::block_api::BufferKindUser>::BufferKind,
184                >
185            >;
186
187            #[inline]
188            fn serialize(&self) -> $crate::common::hazmat::SerializedState<Self> {
189                let serialized_core = self.core.serialize();
190                let serialized_buf = self.buffer.serialize();
191                serialized_core.concat(serialized_buf)
192            }
193
194            #[inline]
195            fn deserialize(
196                serialized_state: &$crate::common::hazmat::SerializedState<Self>,
197            ) -> Result<Self, $crate::common::hazmat::DeserializeStateError> {
198                use $crate::common::hazmat::{SerializableState, DeserializeStateError};
199
200                let (serialized_core, serialized_buf) = serialized_state
201                    .split_ref::<<$core_ty as SerializableState>::SerializedStateSize>();
202
203                let core = SerializableState::deserialize(serialized_core)?;
204                let buffer = $crate::block_buffer::BlockBuffer::deserialize(serialized_buf)
205                    .map_err(|_| DeserializeStateError)?;
206
207                Ok(Self { core, buffer })
208            }
209        }
210    };
211}