1use alloc::vec::Vec;
8use core::fmt;
9use digest::Digest;
10use digest::typenum::U32;
11
12use crate::list::encode_var_list_payloads;
13use crate::merkle::{merkleize, pack_bytes};
14use crate::{BYTES_PER_LENGTH_OFFSET, Decode, DecodeError, Encode, HashTreeRoot, read_offset};
15
16pub struct FixedVector<T, const N: usize> {
20 inner: Vec<T>,
21}
22
23impl<T, const N: usize> FixedVector<T, N> {
24 pub fn from_vec(v: Vec<T>) -> Result<Self, DecodeError> {
26 if v.len() != N {
27 return Err(DecodeError::LengthMismatch {
28 expected: N,
29 actual: v.len(),
30 });
31 }
32 Ok(Self { inner: v })
33 }
34
35 pub fn as_slice(&self) -> &[T] {
37 &self.inner
38 }
39
40 pub const fn len(&self) -> usize {
42 N
43 }
44
45 pub const fn is_empty(&self) -> bool {
47 N == 0
48 }
49
50 pub fn into_inner(self) -> Vec<T> {
52 self.inner
53 }
54}
55
56impl<T: Clone, const N: usize> FixedVector<T, N> {
57 pub fn from_slice(items: &[T]) -> Result<Self, DecodeError> {
59 if items.len() != N {
60 return Err(DecodeError::LengthMismatch {
61 expected: N,
62 actual: items.len(),
63 });
64 }
65 let mut v: Vec<T> = Vec::with_capacity(N);
66 for t in items {
67 v.push(t.clone());
68 }
69 Ok(Self { inner: v })
70 }
71}
72
73impl<T, const N: usize> core::ops::Deref for FixedVector<T, N> {
74 type Target = [T];
75 fn deref(&self) -> &[T] {
76 &self.inner
77 }
78}
79
80impl<T: fmt::Debug, const N: usize> fmt::Debug for FixedVector<T, N> {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 f.debug_struct("FixedVector")
83 .field("len", &N)
84 .field("inner", &&self.inner[..])
85 .finish()
86 }
87}
88
89impl<T: Clone, const N: usize> Clone for FixedVector<T, N> {
90 fn clone(&self) -> Self {
91 Self {
92 inner: self.inner.clone(),
93 }
94 }
95}
96
97impl<T: PartialEq, const N: usize> PartialEq for FixedVector<T, N> {
98 fn eq(&self, other: &Self) -> bool {
99 self.inner == other.inner
100 }
101}
102
103impl<T: Eq, const N: usize> Eq for FixedVector<T, N> {}
104
105impl<T: Encode, const N: usize> Encode for FixedVector<T, N> {
110 fn is_ssz_fixed_len() -> bool {
111 T::is_ssz_fixed_len()
112 }
113 fn ssz_fixed_len() -> usize {
114 if T::is_ssz_fixed_len() {
115 T::ssz_fixed_len() * N
116 } else {
117 BYTES_PER_LENGTH_OFFSET
118 }
119 }
120 fn ssz_bytes_len(&self) -> usize {
121 if T::is_ssz_fixed_len() {
122 T::ssz_fixed_len() * N
123 } else {
124 let mut total = N * BYTES_PER_LENGTH_OFFSET;
125 for item in &self.inner {
126 total += item.ssz_bytes_len();
127 }
128 total
129 }
130 }
131 fn ssz_append(&self, buf: &mut Vec<u8>) {
132 encode_fixed_vector(self.inner.iter(), buf);
133 }
134}
135
136impl<T: Decode, const N: usize> Decode for FixedVector<T, N> {
137 fn is_ssz_fixed_len() -> bool {
138 T::is_ssz_fixed_len()
139 }
140 fn ssz_fixed_len() -> usize {
141 if T::is_ssz_fixed_len() {
142 T::ssz_fixed_len() * N
143 } else {
144 BYTES_PER_LENGTH_OFFSET
145 }
146 }
147 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
148 let decoded = decode_fixed_vector::<T>(bytes, N)?;
149 let mut inner: Vec<T> = Vec::with_capacity(N);
150 for t in decoded {
151 inner.push(t);
152 }
153 Ok(Self { inner })
154 }
155}
156
157impl<T: HashTreeRoot + Encode, const N: usize> HashTreeRoot for FixedVector<T, N> {
158 fn hash_tree_root<D: Digest<OutputSize = U32>>(&self) -> [u8; 32] {
159 if T::is_basic_type() {
160 let mut buf: Vec<u8> = Vec::new();
162 for t in &self.inner {
163 t.ssz_append(&mut buf);
164 }
165 let chunks = pack_bytes(&buf);
166 let total_bytes = N.saturating_mul(T::ssz_fixed_len());
167 let chunk_limit = total_bytes.div_ceil(32).max(1);
168 merkleize::<D>(&chunks, chunk_limit)
169 } else {
170 let roots: Vec<[u8; 32]> = self.inner.iter().map(|t| t.hash_tree_root::<D>()).collect();
172 merkleize::<D>(&roots, N.max(1))
173 }
174 }
175}
176
177pub(crate) fn encode_fixed_vector<'a, T, I>(items: I, buf: &mut Vec<u8>)
182where
183 T: Encode + 'a,
184 I: Iterator<Item = &'a T>,
185{
186 let items_vec: Vec<&T> = items.collect();
187 if T::is_ssz_fixed_len() {
188 for item in &items_vec {
189 item.ssz_append(buf);
190 }
191 } else {
192 encode_var_list_payloads(&items_vec, buf);
193 }
194}
195
196pub(crate) fn decode_fixed_vector<T: Decode>(
197 bytes: &[u8],
198 n: usize,
199) -> Result<Vec<T>, DecodeError> {
200 if T::is_ssz_fixed_len() {
201 let elem_size = T::ssz_fixed_len();
202 let expected = elem_size.saturating_mul(n);
203 if bytes.len() != expected {
204 return Err(DecodeError::LengthMismatch {
205 expected,
206 actual: bytes.len(),
207 });
208 }
209 let mut out = Vec::with_capacity(n);
210 for i in 0..n {
211 let start = i * elem_size;
212 out.push(T::from_ssz_bytes(&bytes[start..start + elem_size])?);
213 }
214 Ok(out)
215 } else {
216 decode_var_collection::<T>(bytes, Some(n))
217 }
218}
219
220pub(crate) fn decode_var_collection<T: Decode>(
226 bytes: &[u8],
227 expected_len: Option<usize>,
228) -> Result<Vec<T>, DecodeError> {
229 if bytes.is_empty() {
230 return match expected_len {
231 None | Some(0) => Ok(Vec::new()),
232 Some(n) => Err(DecodeError::LengthMismatch {
233 expected: n,
234 actual: 0,
235 }),
236 };
237 }
238 let first = read_offset(bytes, 0)?;
239 if first % BYTES_PER_LENGTH_OFFSET != 0 {
240 return Err(DecodeError::InvalidOffset {
241 offset: first,
242 len: bytes.len(),
243 fixed: 0,
244 });
245 }
246 if first > bytes.len() {
247 return Err(DecodeError::InvalidOffset {
248 offset: first,
249 len: bytes.len(),
250 fixed: 0,
251 });
252 }
253 let n = first / BYTES_PER_LENGTH_OFFSET;
254 if let Some(expected) = expected_len
255 && n != expected
256 {
257 return Err(DecodeError::LengthMismatch {
258 expected,
259 actual: n,
260 });
261 }
262 let mut offsets = Vec::with_capacity(n + 1);
263 offsets.push(first);
264 for i in 1..n {
265 let off = read_offset(bytes, i * BYTES_PER_LENGTH_OFFSET)?;
266 if off < offsets[i - 1] {
267 return Err(DecodeError::OffsetsNotMonotonic {
268 prev: offsets[i - 1],
269 curr: off,
270 });
271 }
272 if off > bytes.len() {
273 return Err(DecodeError::InvalidOffset {
274 offset: off,
275 len: bytes.len(),
276 fixed: first,
277 });
278 }
279 offsets.push(off);
280 }
281 offsets.push(bytes.len());
282
283 let mut out = Vec::with_capacity(n);
284 for i in 0..n {
285 let slice = &bytes[offsets[i]..offsets[i + 1]];
286 out.push(T::from_ssz_bytes(slice)?);
287 }
288 Ok(out)
289}