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