digest/block_api/
ct_variable.rs

1use super::{
2    AlgorithmName, Buffer, BufferKindUser, FixedOutputCore, Reset, TruncSide, UpdateCore,
3    VariableOutputCore, VariableOutputCoreCustomized,
4};
5#[cfg(feature = "mac")]
6use crate::MacMarker;
7use crate::{CollisionResistance, CustomizedInit, HashMarker};
8use common::{
9    Block, BlockSizeUser, OutputSizeUser,
10    array::{Array, ArraySize},
11    hazmat::{DeserializeStateError, SerializableState, SerializedState},
12    typenum::{IsLessOrEqual, True},
13};
14use core::{fmt, marker::PhantomData};
15
16/// Wrapper around [`VariableOutputCore`] which selects output size at compile time.
17pub struct CtOutWrapper<T, OutSize>
18where
19    T: VariableOutputCore,
20    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
21{
22    inner: T,
23    _out: PhantomData<OutSize>,
24}
25
26impl<T, OutSize> Clone for CtOutWrapper<T, OutSize>
27where
28    T: VariableOutputCore + Clone,
29    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
30{
31    fn clone(&self) -> Self {
32        Self {
33            inner: self.inner.clone(),
34            _out: PhantomData,
35        }
36    }
37}
38
39impl<T, OutSize> HashMarker for CtOutWrapper<T, OutSize>
40where
41    T: VariableOutputCore + HashMarker,
42    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
43{
44}
45
46#[cfg(feature = "mac")]
47impl<T, OutSize> MacMarker for CtOutWrapper<T, OutSize>
48where
49    T: VariableOutputCore + MacMarker,
50    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
51{
52}
53
54impl<T, OutSize> CollisionResistance for CtOutWrapper<T, OutSize>
55where
56    T: VariableOutputCore + CollisionResistance,
57    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
58{
59    type CollisionResistance = T::CollisionResistance;
60}
61
62impl<T, OutSize> BlockSizeUser for CtOutWrapper<T, OutSize>
63where
64    T: VariableOutputCore,
65    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
66{
67    type BlockSize = T::BlockSize;
68}
69
70impl<T, OutSize> UpdateCore for CtOutWrapper<T, OutSize>
71where
72    T: VariableOutputCore,
73    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
74{
75    #[inline]
76    fn update_blocks(&mut self, blocks: &[Block<Self>]) {
77        self.inner.update_blocks(blocks);
78    }
79}
80
81impl<T, OutSize> OutputSizeUser for CtOutWrapper<T, OutSize>
82where
83    T: VariableOutputCore,
84    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
85{
86    type OutputSize = OutSize;
87}
88
89impl<T, OutSize> BufferKindUser for CtOutWrapper<T, OutSize>
90where
91    T: VariableOutputCore,
92    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
93{
94    type BufferKind = T::BufferKind;
95}
96
97impl<T, OutSize> FixedOutputCore for CtOutWrapper<T, OutSize>
98where
99    T: VariableOutputCore,
100    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
101{
102    #[inline]
103    fn finalize_fixed_core(
104        &mut self,
105        buffer: &mut Buffer<Self>,
106        out: &mut Array<u8, Self::OutputSize>,
107    ) {
108        let mut full_res = Default::default();
109        self.inner.finalize_variable_core(buffer, &mut full_res);
110        let n = out.len();
111        let m = full_res.len() - n;
112        match T::TRUNC_SIDE {
113            TruncSide::Left => out.copy_from_slice(&full_res[..n]),
114            TruncSide::Right => out.copy_from_slice(&full_res[m..]),
115        }
116    }
117}
118
119impl<T, OutSize> Default for CtOutWrapper<T, OutSize>
120where
121    T: VariableOutputCore,
122    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
123{
124    #[inline]
125    fn default() -> Self {
126        Self {
127            inner: T::new(OutSize::USIZE).unwrap(),
128            _out: PhantomData,
129        }
130    }
131}
132
133impl<T, OutSize> CustomizedInit for CtOutWrapper<T, OutSize>
134where
135    T: VariableOutputCoreCustomized,
136    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
137{
138    #[inline]
139    fn new_customized(customization: &[u8]) -> Self {
140        Self {
141            inner: T::new_customized(customization, OutSize::USIZE),
142            _out: PhantomData,
143        }
144    }
145}
146
147impl<T, OutSize> Reset for CtOutWrapper<T, OutSize>
148where
149    T: VariableOutputCore,
150    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
151{
152    #[inline]
153    fn reset(&mut self) {
154        *self = Default::default();
155    }
156}
157
158impl<T, OutSize> AlgorithmName for CtOutWrapper<T, OutSize>
159where
160    T: VariableOutputCore + AlgorithmName,
161    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
162{
163    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
164        T::write_alg_name(f)?;
165        f.write_str("_")?;
166        write!(f, "{}", OutSize::USIZE)
167    }
168}
169
170#[cfg(feature = "zeroize")]
171impl<T, OutSize> zeroize::ZeroizeOnDrop for CtOutWrapper<T, OutSize>
172where
173    T: VariableOutputCore + zeroize::ZeroizeOnDrop,
174    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
175{
176}
177
178impl<T, OutSize> fmt::Debug for CtOutWrapper<T, OutSize>
179where
180    T: VariableOutputCore + AlgorithmName,
181    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
182{
183    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184        Self::write_alg_name(f)
185    }
186}
187
188impl<T, OutSize> SerializableState for CtOutWrapper<T, OutSize>
189where
190    T: VariableOutputCore + SerializableState,
191    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
192{
193    type SerializedStateSize = <T as SerializableState>::SerializedStateSize;
194
195    fn serialize(&self) -> SerializedState<Self> {
196        self.inner.serialize()
197    }
198
199    fn deserialize(
200        serialized_state: &SerializedState<Self>,
201    ) -> Result<Self, DeserializeStateError> {
202        let _out = PhantomData;
203        T::deserialize(serialized_state).map(|inner| Self { inner, _out })
204    }
205}