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