redoubt_codec_core/collections/
vec.rs1use alloc::vec::Vec;
6
7use redoubt_zero::{FastZeroizable, ZeroizeMetadata};
8
9use crate::codec_buffer::RedoubtCodecBuffer;
10use crate::error::{DecodeError, EncodeError, OverflowError};
11use crate::traits::{
12 BytesRequired, Decode, DecodeSlice, Encode, EncodeSlice, PreAlloc, TryDecode, TryEncode,
13};
14use crate::zeroizing::Zeroizing;
15
16use super::helpers::{header_size, process_header, write_header};
17
18#[cfg(feature = "zeroize")]
20#[cold]
21#[inline(never)]
22fn cleanup_encode_error<T: FastZeroizable + ZeroizeMetadata>(
23 vec: &mut Vec<T>,
24 buf: &mut RedoubtCodecBuffer,
25) {
26 vec.fast_zeroize();
27 buf.fast_zeroize();
28}
29
30#[cfg(feature = "zeroize")]
32#[cold]
33#[inline(never)]
34fn cleanup_decode_error<T: FastZeroizable + ZeroizeMetadata>(
35 vec: &mut Vec<T>,
36 buf: &mut &mut [u8],
37) {
38 vec.fast_zeroize();
39 buf.fast_zeroize();
40}
41
42impl<T> BytesRequired for Vec<T>
43where
44 T: BytesRequired,
45{
46 fn encode_bytes_required(&self) -> Result<usize, OverflowError> {
47 let mut bytes_required = header_size();
48
49 for elem in self.iter() {
50 let new_bytes_required = bytes_required.wrapping_add(elem.encode_bytes_required()?);
51
52 if new_bytes_required < bytes_required {
53 return Err(OverflowError {
54 reason: "Vec::encode_bytes_required overflow".into(),
55 });
56 }
57
58 bytes_required = new_bytes_required;
59 }
60
61 Ok(bytes_required)
62 }
63}
64
65impl<T> TryEncode for Vec<T>
66where
67 T: EncodeSlice + BytesRequired + FastZeroizable + ZeroizeMetadata,
68{
69 fn try_encode_into(&mut self, buf: &mut RedoubtCodecBuffer) -> Result<(), EncodeError> {
70 let mut size = Zeroizing::from(&mut self.len());
71 let mut bytes_required = Zeroizing::from(&mut self.encode_bytes_required()?);
72
73 write_header(buf, &mut size, &mut bytes_required)?;
74
75 T::encode_slice_into(self.as_mut_slice(), buf)
76 }
77}
78
79impl<T> Encode for Vec<T>
80where
81 T: EncodeSlice + BytesRequired + FastZeroizable + ZeroizeMetadata,
82{
83 #[inline(always)]
84 fn encode_into(&mut self, buf: &mut RedoubtCodecBuffer) -> Result<(), EncodeError> {
85 let result = self.try_encode_into(buf);
86
87 #[cfg(feature = "zeroize")]
88 if result.is_err() {
89 cleanup_encode_error(self, buf);
90 } else {
91 self.fast_zeroize();
92 }
93
94 result
95 }
96}
97
98impl<T> EncodeSlice for Vec<T>
99where
100 T: EncodeSlice + BytesRequired + FastZeroizable + ZeroizeMetadata,
101{
102 #[inline(always)]
103 fn encode_slice_into(
104 slice: &mut [Self],
105 buf: &mut RedoubtCodecBuffer,
106 ) -> Result<(), EncodeError> {
107 for elem in slice.iter_mut() {
108 elem.encode_into(buf)?;
109 }
110
111 Ok(())
112 }
113}
114
115impl<T> TryDecode for Vec<T>
116where
117 T: DecodeSlice + PreAlloc + FastZeroizable + ZeroizeMetadata,
118{
119 #[inline(always)]
120 fn try_decode_from(&mut self, buf: &mut &mut [u8]) -> Result<(), DecodeError> {
121 let mut size = Zeroizing::from(&mut 0);
122
123 process_header(buf, &mut size)?;
124
125 self.prealloc(*size);
126
127 T::decode_slice_from(self.as_mut_slice(), buf)
128 }
129}
130
131impl<T> Decode for Vec<T>
132where
133 T: DecodeSlice + PreAlloc + FastZeroizable + ZeroizeMetadata,
134{
135 #[inline(always)]
136 fn decode_from(&mut self, buf: &mut &mut [u8]) -> Result<(), DecodeError> {
137 let result = self.try_decode_from(buf);
138
139 #[cfg(feature = "zeroize")]
140 if result.is_err() {
141 cleanup_decode_error(self, buf);
142 }
143
144 result
145 }
146}
147
148impl<T> DecodeSlice for Vec<T>
149where
150 T: DecodeSlice + PreAlloc + FastZeroizable + ZeroizeMetadata,
151{
152 #[inline(always)]
153 fn decode_slice_from(slice: &mut [Self], buf: &mut &mut [u8]) -> Result<(), DecodeError> {
154 for elem in slice.iter_mut() {
155 elem.decode_from(buf)?;
156 }
157
158 Ok(())
159 }
160}
161
162#[inline(always)]
163pub(crate) fn vec_prealloc<T: PreAlloc + FastZeroizable + ZeroizeMetadata>(
164 vec: &mut Vec<T>,
165 size: usize,
166 zero_init: bool,
167) {
168 vec.shrink_to_fit();
169 vec.reserve_exact(size);
170
171 if zero_init {
172 vec.fast_zeroize();
173 unsafe { vec.set_len(size) };
174 } else {
175 vec.resize_with(size, Default::default);
176 vec.fast_zeroize();
177 }
178}
179
180impl<T: PreAlloc + FastZeroizable + ZeroizeMetadata> PreAlloc for Vec<T> {
181 const ZERO_INIT: bool = false;
183
184 #[inline(always)]
185 fn prealloc(&mut self, size: usize) {
186 vec_prealloc(self, size, T::ZERO_INIT);
187 }
188}