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
16pub 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}