1use super::*;
2use crate::decode::try_from_iter::{TryCollect, TryFromIter};
3use alloy_primitives::{Address, Bloom, Bytes, FixedBytes, U128, U256};
4use core::num::NonZeroUsize;
5use itertools::process_results;
6use smallvec::SmallVec;
7use std::collections::{BTreeMap, BTreeSet};
8use std::iter::{self, FromIterator};
9use std::sync::Arc;
10
11macro_rules! impl_decodable_for_uint {
12 ($type: ident, $bit_size: expr) => {
13 impl Decode for $type {
14 #[inline(always)]
15 fn is_ssz_fixed_len() -> bool {
16 true
17 }
18
19 #[inline(always)]
20 fn ssz_fixed_len() -> usize {
21 $bit_size / 8
22 }
23
24 #[inline(always)]
25 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
26 let len = bytes.len();
27 let expected = <Self as Decode>::ssz_fixed_len();
28
29 if len != expected {
30 Err(DecodeError::InvalidByteLength { len, expected })
31 } else {
32 let mut array: [u8; $bit_size / 8] = std::default::Default::default();
33 array.clone_from_slice(bytes);
34
35 Ok(Self::from_le_bytes(array))
36 }
37 }
38 }
39 };
40}
41
42impl_decodable_for_uint!(u8, 8);
43impl_decodable_for_uint!(u16, 16);
44impl_decodable_for_uint!(u32, 32);
45impl_decodable_for_uint!(u64, 64);
46impl_decodable_for_uint!(u128, 128);
47
48#[cfg(target_pointer_width = "32")]
49impl_decodable_for_uint!(usize, 32);
50
51#[cfg(target_pointer_width = "64")]
52impl_decodable_for_uint!(usize, 64);
53
54macro_rules! impl_decode_for_tuples {
55 ($(
56 $Tuple:ident {
57 $(($idx:tt) -> $T:ident)+
58 }
59 )+) => {
60 $(
61 impl<$($T: Decode),+> Decode for ($($T,)+) {
62 fn is_ssz_fixed_len() -> bool {
63 $(
64 <$T as Decode>::is_ssz_fixed_len() &&
65 )*
66 true
67 }
68
69 fn ssz_fixed_len() -> usize {
70 if <Self as Decode>::is_ssz_fixed_len() {
71 $(
72 <$T as Decode>::ssz_fixed_len() +
73 )*
74 0
75 } else {
76 BYTES_PER_LENGTH_OFFSET
77 }
78 }
79
80 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
81 let mut builder = SszDecoderBuilder::new(bytes);
82
83 $(
84 builder.register_type::<$T>()?;
85 )*
86
87 let mut decoder = builder.build()?;
88
89 Ok(($(
90 decoder.decode_next::<$T>()?,
91 )*
92 ))
93 }
94 }
95 )+
96 }
97}
98
99impl_decode_for_tuples! {
100 Tuple2 {
101 (0) -> A
102 (1) -> B
103 }
104 Tuple3 {
105 (0) -> A
106 (1) -> B
107 (2) -> C
108 }
109 Tuple4 {
110 (0) -> A
111 (1) -> B
112 (2) -> C
113 (3) -> D
114 }
115 Tuple5 {
116 (0) -> A
117 (1) -> B
118 (2) -> C
119 (3) -> D
120 (4) -> E
121 }
122 Tuple6 {
123 (0) -> A
124 (1) -> B
125 (2) -> C
126 (3) -> D
127 (4) -> E
128 (5) -> F
129 }
130 Tuple7 {
131 (0) -> A
132 (1) -> B
133 (2) -> C
134 (3) -> D
135 (4) -> E
136 (5) -> F
137 (6) -> G
138 }
139 Tuple8 {
140 (0) -> A
141 (1) -> B
142 (2) -> C
143 (3) -> D
144 (4) -> E
145 (5) -> F
146 (6) -> G
147 (7) -> H
148 }
149 Tuple9 {
150 (0) -> A
151 (1) -> B
152 (2) -> C
153 (3) -> D
154 (4) -> E
155 (5) -> F
156 (6) -> G
157 (7) -> H
158 (8) -> I
159 }
160 Tuple10 {
161 (0) -> A
162 (1) -> B
163 (2) -> C
164 (3) -> D
165 (4) -> E
166 (5) -> F
167 (6) -> G
168 (7) -> H
169 (8) -> I
170 (9) -> J
171 }
172 Tuple11 {
173 (0) -> A
174 (1) -> B
175 (2) -> C
176 (3) -> D
177 (4) -> E
178 (5) -> F
179 (6) -> G
180 (7) -> H
181 (8) -> I
182 (9) -> J
183 (10) -> K
184 }
185 Tuple12 {
186 (0) -> A
187 (1) -> B
188 (2) -> C
189 (3) -> D
190 (4) -> E
191 (5) -> F
192 (6) -> G
193 (7) -> H
194 (8) -> I
195 (9) -> J
196 (10) -> K
197 (11) -> L
198 }
199}
200
201impl Decode for bool {
202 fn is_ssz_fixed_len() -> bool {
203 true
204 }
205
206 fn ssz_fixed_len() -> usize {
207 1
208 }
209
210 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
211 let len = bytes.len();
212 let expected = <Self as Decode>::ssz_fixed_len();
213
214 if len != expected {
215 Err(DecodeError::InvalidByteLength { len, expected })
216 } else {
217 match bytes[0] {
218 0b0000_0000 => Ok(false),
219 0b0000_0001 => Ok(true),
220 _ => Err(DecodeError::BytesInvalid(format!(
221 "Out-of-range for boolean: {}",
222 bytes[0]
223 ))),
224 }
225 }
226 }
227}
228
229impl Decode for NonZeroUsize {
230 fn is_ssz_fixed_len() -> bool {
231 <usize as Decode>::is_ssz_fixed_len()
232 }
233
234 fn ssz_fixed_len() -> usize {
235 <usize as Decode>::ssz_fixed_len()
236 }
237
238 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
239 let x = usize::from_ssz_bytes(bytes)?;
240
241 if x == 0 {
242 Err(DecodeError::BytesInvalid(
243 "NonZeroUsize cannot be zero.".to_string(),
244 ))
245 } else {
246 Ok(NonZeroUsize::new(x).unwrap())
249 }
250 }
251}
252
253impl<T: Decode> Decode for Option<T> {
254 fn is_ssz_fixed_len() -> bool {
255 false
256 }
257 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
258 let (selector, body) = split_union_bytes(bytes)?;
259 match selector.into() {
260 0u8 => {
261 if body.is_empty() {
262 Ok(None)
263 } else {
264 Err(DecodeError::InvalidByteLength {
265 len: body.len(),
266 expected: 0,
267 })
268 }
269 }
270 1u8 => <T as Decode>::from_ssz_bytes(body).map(Option::Some),
271 other => Err(DecodeError::UnionSelectorInvalid(other)),
272 }
273 }
274}
275
276impl<T: Decode> Decode for Arc<T> {
277 fn is_ssz_fixed_len() -> bool {
278 T::is_ssz_fixed_len()
279 }
280
281 fn ssz_fixed_len() -> usize {
282 T::ssz_fixed_len()
283 }
284
285 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
286 T::from_ssz_bytes(bytes).map(Arc::new)
287 }
288}
289
290impl Decode for Address {
291 fn is_ssz_fixed_len() -> bool {
292 true
293 }
294
295 fn ssz_fixed_len() -> usize {
296 20
297 }
298
299 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
300 let len = bytes.len();
301 let expected = <Self as Decode>::ssz_fixed_len();
302
303 if len != expected {
304 Err(DecodeError::InvalidByteLength { len, expected })
305 } else {
306 Ok(Self::from_slice(bytes))
307 }
308 }
309}
310
311impl<const N: usize> Decode for FixedBytes<N> {
312 fn is_ssz_fixed_len() -> bool {
313 true
314 }
315
316 fn ssz_fixed_len() -> usize {
317 N
318 }
319
320 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
321 if bytes.len() != N {
322 return Err(DecodeError::InvalidByteLength {
323 len: bytes.len(),
324 expected: N,
325 });
326 }
327
328 let mut fixed_array = [0u8; N];
329 fixed_array.copy_from_slice(bytes);
330
331 Ok(Self(fixed_array))
332 }
333}
334
335impl Decode for Bloom {
336 fn is_ssz_fixed_len() -> bool {
337 true
338 }
339
340 fn ssz_fixed_len() -> usize {
341 256
342 }
343
344 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
345 let len = bytes.len();
346 let expected = <Self as Decode>::ssz_fixed_len();
347
348 if len != expected {
349 Err(DecodeError::InvalidByteLength { len, expected })
350 } else {
351 Ok(Self::from_slice(bytes))
352 }
353 }
354}
355
356impl Decode for U256 {
357 fn is_ssz_fixed_len() -> bool {
358 true
359 }
360
361 fn ssz_fixed_len() -> usize {
362 32
363 }
364
365 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
366 let len = bytes.len();
367 let expected = <Self as Decode>::ssz_fixed_len();
368
369 if len != expected {
370 Err(DecodeError::InvalidByteLength { len, expected })
371 } else {
372 Ok(U256::from_le_slice(bytes))
373 }
374 }
375}
376
377impl Decode for Bytes {
378 #[inline]
379 fn is_ssz_fixed_len() -> bool {
380 false
381 }
382
383 #[inline]
384 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
385 Ok(bytes.to_vec().into())
386 }
387}
388
389impl Decode for U128 {
390 fn is_ssz_fixed_len() -> bool {
391 true
392 }
393
394 fn ssz_fixed_len() -> usize {
395 16
396 }
397
398 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
399 let len = bytes.len();
400 let expected = <Self as Decode>::ssz_fixed_len();
401
402 if len != expected {
403 Err(DecodeError::InvalidByteLength { len, expected })
404 } else {
405 Ok(U128::from_le_slice(bytes))
406 }
407 }
408}
409
410impl<const N: usize> Decode for [u8; N] {
411 fn is_ssz_fixed_len() -> bool {
412 true
413 }
414
415 fn ssz_fixed_len() -> usize {
416 N
417 }
418
419 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
420 let len = bytes.len();
421 let expected = <Self as Decode>::ssz_fixed_len();
422
423 if len != expected {
424 Err(DecodeError::InvalidByteLength { len, expected })
425 } else {
426 let mut array: [u8; N] = [0; N];
427 array.copy_from_slice(bytes);
428
429 Ok(array)
430 }
431 }
432}
433
434impl<T: Decode> Decode for Vec<T> {
435 fn is_ssz_fixed_len() -> bool {
436 false
437 }
438
439 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
440 if bytes.is_empty() {
441 Ok(vec![])
442 } else if T::is_ssz_fixed_len() {
443 bytes
444 .chunks(T::ssz_fixed_len())
445 .map(T::from_ssz_bytes)
446 .collect()
447 } else {
448 decode_list_of_variable_length_items(bytes, None)
449 }
450 }
451}
452
453impl<T: Decode, const N: usize> Decode for SmallVec<[T; N]> {
454 fn is_ssz_fixed_len() -> bool {
455 false
456 }
457
458 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
459 if bytes.is_empty() {
460 Ok(SmallVec::new())
461 } else if T::is_ssz_fixed_len() {
462 bytes
463 .chunks(T::ssz_fixed_len())
464 .map(T::from_ssz_bytes)
465 .collect()
466 } else {
467 decode_list_of_variable_length_items(bytes, None)
468 }
469 }
470}
471
472impl<K, V> Decode for BTreeMap<K, V>
473where
474 K: Decode + Ord,
475 V: Decode,
476{
477 fn is_ssz_fixed_len() -> bool {
478 false
479 }
480
481 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
482 if bytes.is_empty() {
483 Ok(Self::from_iter(iter::empty()))
484 } else if <(K, V)>::is_ssz_fixed_len() {
485 bytes
486 .chunks(<(K, V)>::ssz_fixed_len())
487 .map(<(K, V)>::from_ssz_bytes)
488 .collect()
489 } else {
490 decode_list_of_variable_length_items(bytes, None)
491 }
492 }
493}
494
495impl<T> Decode for BTreeSet<T>
496where
497 T: Decode + Ord,
498{
499 fn is_ssz_fixed_len() -> bool {
500 false
501 }
502
503 fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
504 if bytes.is_empty() {
505 Ok(Self::from_iter(iter::empty()))
506 } else if T::is_ssz_fixed_len() {
507 bytes
508 .chunks(T::ssz_fixed_len())
509 .map(T::from_ssz_bytes)
510 .collect()
511 } else {
512 decode_list_of_variable_length_items(bytes, None)
513 }
514 }
515}
516
517pub fn decode_list_of_variable_length_items<T: Decode, Container: TryFromIter<T>>(
523 bytes: &[u8],
524 max_len: Option<usize>,
525) -> Result<Container, DecodeError> {
526 if bytes.is_empty() {
527 return Container::try_from_iter(iter::empty()).map_err(|e| {
528 DecodeError::BytesInvalid(format!("Error trying to collect empty list: {:?}", e))
529 });
530 }
531
532 let first_offset = read_offset(bytes)?;
533 sanitize_offset(first_offset, None, bytes.len(), Some(first_offset))?;
534
535 if first_offset % BYTES_PER_LENGTH_OFFSET != 0 || first_offset < BYTES_PER_LENGTH_OFFSET {
536 return Err(DecodeError::InvalidListFixedBytesLen(first_offset));
537 }
538
539 let num_items = first_offset / BYTES_PER_LENGTH_OFFSET;
540
541 if max_len.is_some_and(|max| num_items > max) {
542 return Err(DecodeError::BytesInvalid(format!(
543 "Variable length list of {} items exceeds maximum of {:?}",
544 num_items, max_len
545 )));
546 }
547
548 let mut offset = first_offset;
549 process_results(
550 (1..=num_items).map(|i| {
551 let slice_option = if i == num_items {
552 bytes.get(offset..)
553 } else {
554 let start = offset;
555
556 let next_offset = read_offset(&bytes[(i * BYTES_PER_LENGTH_OFFSET)..])?;
557 offset =
558 sanitize_offset(next_offset, Some(offset), bytes.len(), Some(first_offset))?;
559
560 bytes.get(start..offset)
561 };
562
563 let slice = slice_option.ok_or(DecodeError::OutOfBoundsByte { i: offset })?;
564 T::from_ssz_bytes(slice)
565 }),
566 |iter| iter.try_collect(),
567 )?
568 .map_err(|e| DecodeError::BytesInvalid(format!("Error collecting into container: {:?}", e)))
569}
570
571#[cfg(test)]
572mod tests {
573 use super::*;
574 use alloy_primitives::B256;
575
576 #[test]
580 fn invalid_u8_array_4() {
581 assert_eq!(
582 <[u8; 4]>::from_ssz_bytes(&[0; 3]),
583 Err(DecodeError::InvalidByteLength {
584 len: 3,
585 expected: 4
586 })
587 );
588
589 assert_eq!(
590 <[u8; 4]>::from_ssz_bytes(&[0; 5]),
591 Err(DecodeError::InvalidByteLength {
592 len: 5,
593 expected: 4
594 })
595 );
596 }
597
598 #[test]
599 fn invalid_bool() {
600 assert_eq!(
601 bool::from_ssz_bytes(&[0; 2]),
602 Err(DecodeError::InvalidByteLength {
603 len: 2,
604 expected: 1
605 })
606 );
607
608 assert_eq!(
609 bool::from_ssz_bytes(&[]),
610 Err(DecodeError::InvalidByteLength {
611 len: 0,
612 expected: 1
613 })
614 );
615
616 if let Err(DecodeError::BytesInvalid(_)) = bool::from_ssz_bytes(&[2]) {
617 } else {
619 panic!("Did not return error on invalid bool val")
620 }
621 }
622
623 #[test]
624 fn invalid_b256() {
625 assert_eq!(
626 B256::from_ssz_bytes(&[0; 33]),
627 Err(DecodeError::InvalidByteLength {
628 len: 33,
629 expected: 32
630 })
631 );
632
633 assert_eq!(
634 B256::from_ssz_bytes(&[0; 31]),
635 Err(DecodeError::InvalidByteLength {
636 len: 31,
637 expected: 32
638 })
639 );
640 }
641
642 #[test]
643 fn empty_list() {
644 let vec: Vec<Vec<u16>> = vec![];
645 let bytes = vec.as_ssz_bytes();
646 assert!(bytes.is_empty());
647 assert_eq!(Vec::from_ssz_bytes(&bytes), Ok(vec),);
648 }
649
650 #[test]
651 fn first_length_points_backwards() {
652 assert_eq!(
653 <Vec<Vec<u16>>>::from_ssz_bytes(&[0, 0, 0, 0]),
654 Err(DecodeError::InvalidListFixedBytesLen(0))
655 );
656
657 assert_eq!(
658 <Vec<Vec<u16>>>::from_ssz_bytes(&[1, 0, 0, 0]),
659 Err(DecodeError::InvalidListFixedBytesLen(1))
660 );
661
662 assert_eq!(
663 <Vec<Vec<u16>>>::from_ssz_bytes(&[2, 0, 0, 0]),
664 Err(DecodeError::InvalidListFixedBytesLen(2))
665 );
666
667 assert_eq!(
668 <Vec<Vec<u16>>>::from_ssz_bytes(&[3, 0, 0, 0]),
669 Err(DecodeError::InvalidListFixedBytesLen(3))
670 );
671 }
672
673 #[test]
674 fn lengths_are_decreasing() {
675 assert_eq!(
676 <Vec<Vec<u16>>>::from_ssz_bytes(&[12, 0, 0, 0, 14, 0, 0, 0, 12, 0, 0, 0, 1, 0, 1, 0]),
677 Err(DecodeError::OffsetsAreDecreasing(12))
678 );
679 }
680
681 #[test]
682 fn awkward_fixed_length_portion() {
683 assert_eq!(
684 <Vec<Vec<u16>>>::from_ssz_bytes(&[10, 0, 0, 0, 10, 0, 0, 0, 0, 0]),
685 Err(DecodeError::InvalidListFixedBytesLen(10))
686 );
687 }
688
689 #[test]
690 fn length_out_of_bounds() {
691 assert_eq!(
692 <Vec<Vec<u16>>>::from_ssz_bytes(&[5, 0, 0, 0]),
693 Err(DecodeError::OffsetOutOfBounds(5))
694 );
695 assert_eq!(
696 <Vec<Vec<u16>>>::from_ssz_bytes(&[8, 0, 0, 0, 9, 0, 0, 0]),
697 Err(DecodeError::OffsetOutOfBounds(9))
698 );
699 assert_eq!(
700 <Vec<Vec<u16>>>::from_ssz_bytes(&[8, 0, 0, 0, 16, 0, 0, 0]),
701 Err(DecodeError::OffsetOutOfBounds(16))
702 );
703 }
704
705 #[test]
706 fn vec_of_vec_of_u16() {
707 assert_eq!(
708 <Vec<Vec<u16>>>::from_ssz_bytes(&[4, 0, 0, 0]),
709 Ok(vec![vec![]])
710 );
711
712 assert_eq!(
713 <Vec<u16>>::from_ssz_bytes(&[0, 0, 1, 0, 2, 0, 3, 0]),
714 Ok(vec![0, 1, 2, 3])
715 );
716 assert_eq!(<u16>::from_ssz_bytes(&[16, 0]), Ok(16));
717 assert_eq!(<u16>::from_ssz_bytes(&[0, 1]), Ok(256));
718 assert_eq!(<u16>::from_ssz_bytes(&[255, 255]), Ok(65535));
719
720 assert_eq!(
721 <u16>::from_ssz_bytes(&[255]),
722 Err(DecodeError::InvalidByteLength {
723 len: 1,
724 expected: 2
725 })
726 );
727
728 assert_eq!(
729 <u16>::from_ssz_bytes(&[]),
730 Err(DecodeError::InvalidByteLength {
731 len: 0,
732 expected: 2
733 })
734 );
735
736 assert_eq!(
737 <u16>::from_ssz_bytes(&[0, 1, 2]),
738 Err(DecodeError::InvalidByteLength {
739 len: 3,
740 expected: 2
741 })
742 );
743 }
744
745 #[test]
746 fn vec_of_u16() {
747 assert_eq!(<Vec<u16>>::from_ssz_bytes(&[0, 0, 0, 0]), Ok(vec![0, 0]));
748 assert_eq!(
749 <Vec<u16>>::from_ssz_bytes(&[0, 0, 1, 0, 2, 0, 3, 0]),
750 Ok(vec![0, 1, 2, 3])
751 );
752 assert_eq!(<u16>::from_ssz_bytes(&[16, 0]), Ok(16));
753 assert_eq!(<u16>::from_ssz_bytes(&[0, 1]), Ok(256));
754 assert_eq!(<u16>::from_ssz_bytes(&[255, 255]), Ok(65535));
755
756 assert_eq!(
757 <u16>::from_ssz_bytes(&[255]),
758 Err(DecodeError::InvalidByteLength {
759 len: 1,
760 expected: 2
761 })
762 );
763
764 assert_eq!(
765 <u16>::from_ssz_bytes(&[]),
766 Err(DecodeError::InvalidByteLength {
767 len: 0,
768 expected: 2
769 })
770 );
771
772 assert_eq!(
773 <u16>::from_ssz_bytes(&[0, 1, 2]),
774 Err(DecodeError::InvalidByteLength {
775 len: 3,
776 expected: 2
777 })
778 );
779 }
780
781 #[test]
782 fn u16() {
783 assert_eq!(<u16>::from_ssz_bytes(&[0, 0]), Ok(0));
784 assert_eq!(<u16>::from_ssz_bytes(&[16, 0]), Ok(16));
785 assert_eq!(<u16>::from_ssz_bytes(&[0, 1]), Ok(256));
786 assert_eq!(<u16>::from_ssz_bytes(&[255, 255]), Ok(65535));
787
788 assert_eq!(
789 <u16>::from_ssz_bytes(&[255]),
790 Err(DecodeError::InvalidByteLength {
791 len: 1,
792 expected: 2
793 })
794 );
795
796 assert_eq!(
797 <u16>::from_ssz_bytes(&[]),
798 Err(DecodeError::InvalidByteLength {
799 len: 0,
800 expected: 2
801 })
802 );
803
804 assert_eq!(
805 <u16>::from_ssz_bytes(&[0, 1, 2]),
806 Err(DecodeError::InvalidByteLength {
807 len: 3,
808 expected: 2
809 })
810 );
811 }
812
813 #[test]
814 fn tuple() {
815 assert_eq!(<(u16, u16)>::from_ssz_bytes(&[0, 0, 0, 0]), Ok((0, 0)));
816 assert_eq!(<(u16, u16)>::from_ssz_bytes(&[16, 0, 17, 0]), Ok((16, 17)));
817 assert_eq!(<(u16, u16)>::from_ssz_bytes(&[0, 1, 2, 0]), Ok((256, 2)));
818 assert_eq!(
819 <(u16, u16)>::from_ssz_bytes(&[255, 255, 0, 0]),
820 Ok((65535, 0))
821 );
822 }
823
824 #[test]
825 fn vec_of_u128_roundtrip() {
826 let values = vec![
827 vec![0u128, 55u128, u128::MAX, u128::MAX - 3],
828 vec![],
829 vec![u128::MAX],
830 vec![u32::MAX as u128],
831 vec![0, 0, 0, 0],
832 vec![0, 0, 0, 0, 0, 0],
833 ];
834 for vec in values {
835 assert_eq!(
836 Vec::<u128>::from_ssz_bytes(&vec.as_ssz_bytes()).unwrap(),
837 vec
838 );
839 }
840 }
841
842 #[test]
843 fn option_union_rejects_trailing_bytes() {
844 let dirty_bytes: &[u8] = &[0x00, 0xFF];
847
848 assert_eq!(
849 <Option<u8>>::from_ssz_bytes(dirty_bytes),
850 Err(DecodeError::InvalidByteLength {
851 len: 1,
852 expected: 0
853 })
854 );
855
856 let dirty_bytes_multi: &[u8] = &[0x00, 0xFF, 0xAB, 0xCD];
858
859 assert_eq!(
860 <Option<u8>>::from_ssz_bytes(dirty_bytes_multi),
861 Err(DecodeError::InvalidByteLength {
862 len: 3,
863 expected: 0
864 })
865 );
866
867 let valid_none: &[u8] = &[0x00];
869 assert_eq!(<Option<u8>>::from_ssz_bytes(valid_none), Ok(None));
870
871 let valid_some: &[u8] = &[0x01, 0x42];
873 assert_eq!(<Option<u8>>::from_ssz_bytes(valid_some), Ok(Some(0x42)));
874 }
875
876 #[test]
877 fn option_union_invalid_selector() {
878 assert_eq!(
879 <Option::<u8>>::from_ssz_bytes(&[0x02]),
880 Err(DecodeError::UnionSelectorInvalid(2))
881 );
882 assert_eq!(
883 <Option::<u8>>::from_ssz_bytes(&[0xff, 0x00, 0x00]),
884 Err(DecodeError::UnionSelectorInvalid(255))
885 );
886 }
887}