ssz/encode/
impls.rs

1use super::*;
2use alloy_primitives::{Address, Bloom, Bytes, FixedBytes, U128, U256};
3use core::num::NonZeroUsize;
4use smallvec::SmallVec;
5use std::collections::{BTreeMap, BTreeSet};
6use std::sync::Arc;
7
8macro_rules! impl_encodable_for_uint {
9    ($type: ident, $bit_size: expr) => {
10        impl Encode for $type {
11            #[inline(always)]
12            fn is_ssz_fixed_len() -> bool {
13                true
14            }
15
16            #[inline(always)]
17            fn ssz_fixed_len() -> usize {
18                $bit_size / 8
19            }
20
21            #[inline(always)]
22            fn ssz_bytes_len(&self) -> usize {
23                $bit_size / 8
24            }
25
26            #[inline(always)]
27            fn ssz_append(&self, buf: &mut Vec<u8>) {
28                buf.extend_from_slice(&self.to_le_bytes());
29            }
30        }
31    };
32}
33
34impl_encodable_for_uint!(u8, 8);
35impl_encodable_for_uint!(u16, 16);
36impl_encodable_for_uint!(u32, 32);
37impl_encodable_for_uint!(u64, 64);
38impl_encodable_for_uint!(u128, 128);
39
40#[cfg(target_pointer_width = "32")]
41impl_encodable_for_uint!(usize, 32);
42
43#[cfg(target_pointer_width = "64")]
44impl_encodable_for_uint!(usize, 64);
45
46// Based on the `tuple_impls` macro from the standard library.
47macro_rules! impl_encode_for_tuples {
48    ($(
49        $Tuple:ident {
50            $(($idx:tt) -> $T:ident)+
51        }
52    )+) => {
53        $(
54            impl<$($T: Encode),+> Encode for ($($T,)+) {
55                fn is_ssz_fixed_len() -> bool {
56                    $(
57                        <$T as Encode>::is_ssz_fixed_len() &&
58                    )*
59                        true
60                }
61
62                fn ssz_fixed_len() -> usize {
63                    if <Self as Encode>::is_ssz_fixed_len() {
64                        $(
65                            <$T as Encode>::ssz_fixed_len() +
66                        )*
67                            0
68                    } else {
69                        BYTES_PER_LENGTH_OFFSET
70                    }
71                }
72
73                fn ssz_bytes_len(&self) -> usize {
74                    if <Self as Encode>::is_ssz_fixed_len() {
75                        <Self as Encode>::ssz_fixed_len()
76                    } else {
77                        let mut len = 0;
78                        $(
79                            len += if <$T as Encode>::is_ssz_fixed_len() {
80                                <$T as Encode>::ssz_fixed_len()
81                            } else {
82                                BYTES_PER_LENGTH_OFFSET +
83                                self.$idx.ssz_bytes_len()
84                            };
85                        )*
86                        len
87                    }
88                }
89
90                fn ssz_append(&self, buf: &mut Vec<u8>) {
91                    let offset = $(
92                            <$T as Encode>::ssz_fixed_len() +
93                        )*
94                            0;
95
96                    let mut encoder = SszEncoder::container(buf, offset);
97
98                    $(
99                        encoder.append(&self.$idx);
100                    )*
101
102                    encoder.finalize();
103                }
104            }
105        )+
106    }
107}
108
109impl_encode_for_tuples! {
110    Tuple2 {
111        (0) -> A
112        (1) -> B
113    }
114    Tuple3 {
115        (0) -> A
116        (1) -> B
117        (2) -> C
118    }
119    Tuple4 {
120        (0) -> A
121        (1) -> B
122        (2) -> C
123        (3) -> D
124    }
125    Tuple5 {
126        (0) -> A
127        (1) -> B
128        (2) -> C
129        (3) -> D
130        (4) -> E
131    }
132    Tuple6 {
133        (0) -> A
134        (1) -> B
135        (2) -> C
136        (3) -> D
137        (4) -> E
138        (5) -> F
139    }
140    Tuple7 {
141        (0) -> A
142        (1) -> B
143        (2) -> C
144        (3) -> D
145        (4) -> E
146        (5) -> F
147        (6) -> G
148    }
149    Tuple8 {
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    }
159    Tuple9 {
160        (0) -> A
161        (1) -> B
162        (2) -> C
163        (3) -> D
164        (4) -> E
165        (5) -> F
166        (6) -> G
167        (7) -> H
168        (8) -> I
169    }
170    Tuple10 {
171        (0) -> A
172        (1) -> B
173        (2) -> C
174        (3) -> D
175        (4) -> E
176        (5) -> F
177        (6) -> G
178        (7) -> H
179        (8) -> I
180        (9) -> J
181    }
182    Tuple11 {
183        (0) -> A
184        (1) -> B
185        (2) -> C
186        (3) -> D
187        (4) -> E
188        (5) -> F
189        (6) -> G
190        (7) -> H
191        (8) -> I
192        (9) -> J
193        (10) -> K
194    }
195    Tuple12 {
196        (0) -> A
197        (1) -> B
198        (2) -> C
199        (3) -> D
200        (4) -> E
201        (5) -> F
202        (6) -> G
203        (7) -> H
204        (8) -> I
205        (9) -> J
206        (10) -> K
207        (11) -> L
208    }
209}
210
211impl<T: Encode> Encode for Option<T> {
212    fn is_ssz_fixed_len() -> bool {
213        false
214    }
215    fn ssz_append(&self, buf: &mut Vec<u8>) {
216        match self {
217            Option::None => {
218                let union_selector: u8 = 0u8;
219                buf.push(union_selector);
220            }
221            Option::Some(ref inner) => {
222                let union_selector: u8 = 1u8;
223                buf.push(union_selector);
224                inner.ssz_append(buf);
225            }
226        }
227    }
228    fn ssz_bytes_len(&self) -> usize {
229        match self {
230            Option::None => 1usize,
231            Option::Some(ref inner) => inner
232                .ssz_bytes_len()
233                .checked_add(1)
234                .expect("encoded length must be less than usize::max_value"),
235        }
236    }
237}
238
239impl<T: Encode> Encode for Arc<T> {
240    fn is_ssz_fixed_len() -> bool {
241        T::is_ssz_fixed_len()
242    }
243
244    fn ssz_fixed_len() -> usize {
245        T::ssz_fixed_len()
246    }
247
248    fn ssz_append(&self, buf: &mut Vec<u8>) {
249        self.as_ref().ssz_append(buf)
250    }
251
252    fn ssz_bytes_len(&self) -> usize {
253        self.as_ref().ssz_bytes_len()
254    }
255}
256
257// Encode transparently through references.
258impl<T: Encode> Encode for &T {
259    fn is_ssz_fixed_len() -> bool {
260        T::is_ssz_fixed_len()
261    }
262
263    fn ssz_fixed_len() -> usize {
264        T::ssz_fixed_len()
265    }
266
267    fn ssz_append(&self, buf: &mut Vec<u8>) {
268        T::ssz_append(self, buf)
269    }
270
271    fn ssz_bytes_len(&self) -> usize {
272        T::ssz_bytes_len(self)
273    }
274}
275
276/// Compute the encoded length of a vector-like sequence of `T`.
277pub fn sequence_ssz_bytes_len<I, T>(iter: I) -> usize
278where
279    I: Iterator<Item = T> + ExactSizeIterator,
280    T: Encode,
281{
282    // Compute length before doing any iteration.
283    let length = iter.len();
284    if <T as Encode>::is_ssz_fixed_len() {
285        <T as Encode>::ssz_fixed_len() * length
286    } else {
287        let mut len = iter.map(|item| item.ssz_bytes_len()).sum();
288        len += BYTES_PER_LENGTH_OFFSET * length;
289        len
290    }
291}
292
293/// Encode a vector-like sequence of `T`.
294pub fn sequence_ssz_append<I, T>(iter: I, buf: &mut Vec<u8>)
295where
296    I: Iterator<Item = T> + ExactSizeIterator,
297    T: Encode,
298{
299    if T::is_ssz_fixed_len() {
300        buf.reserve(T::ssz_fixed_len() * iter.len());
301
302        for item in iter {
303            item.ssz_append(buf);
304        }
305    } else {
306        let mut encoder = SszEncoder::container(buf, iter.len() * BYTES_PER_LENGTH_OFFSET);
307
308        for item in iter {
309            encoder.append(&item);
310        }
311
312        encoder.finalize();
313    }
314}
315
316impl<T: Encode> Encode for Vec<T> {
317    fn is_ssz_fixed_len() -> bool {
318        false
319    }
320
321    fn ssz_bytes_len(&self) -> usize {
322        sequence_ssz_bytes_len(self.iter())
323    }
324
325    fn ssz_append(&self, buf: &mut Vec<u8>) {
326        sequence_ssz_append(self.iter(), buf)
327    }
328}
329
330impl<T: Encode, const N: usize> Encode for SmallVec<[T; N]> {
331    fn is_ssz_fixed_len() -> bool {
332        false
333    }
334
335    fn ssz_bytes_len(&self) -> usize {
336        sequence_ssz_bytes_len(self.iter())
337    }
338
339    fn ssz_append(&self, buf: &mut Vec<u8>) {
340        sequence_ssz_append(self.iter(), buf)
341    }
342}
343
344impl<K, V> Encode for BTreeMap<K, V>
345where
346    K: Encode + Ord,
347    V: Encode,
348{
349    fn is_ssz_fixed_len() -> bool {
350        false
351    }
352
353    fn ssz_bytes_len(&self) -> usize {
354        sequence_ssz_bytes_len(self.iter())
355    }
356
357    fn ssz_append(&self, buf: &mut Vec<u8>) {
358        sequence_ssz_append(self.iter(), buf)
359    }
360}
361
362impl<T> Encode for BTreeSet<T>
363where
364    T: Encode + Ord,
365{
366    fn is_ssz_fixed_len() -> bool {
367        false
368    }
369
370    fn ssz_bytes_len(&self) -> usize {
371        sequence_ssz_bytes_len(self.iter())
372    }
373
374    fn ssz_append(&self, buf: &mut Vec<u8>) {
375        sequence_ssz_append(self.iter(), buf)
376    }
377}
378
379impl Encode for bool {
380    fn is_ssz_fixed_len() -> bool {
381        true
382    }
383
384    fn ssz_fixed_len() -> usize {
385        1
386    }
387
388    fn ssz_bytes_len(&self) -> usize {
389        1
390    }
391
392    fn ssz_append(&self, buf: &mut Vec<u8>) {
393        buf.extend_from_slice(&(*self as u8).to_le_bytes());
394    }
395}
396
397impl Encode for NonZeroUsize {
398    fn is_ssz_fixed_len() -> bool {
399        <usize as Encode>::is_ssz_fixed_len()
400    }
401
402    fn ssz_fixed_len() -> usize {
403        <usize as Encode>::ssz_fixed_len()
404    }
405
406    fn ssz_bytes_len(&self) -> usize {
407        std::mem::size_of::<usize>()
408    }
409
410    fn ssz_append(&self, buf: &mut Vec<u8>) {
411        self.get().ssz_append(buf)
412    }
413}
414
415impl Encode for Address {
416    fn is_ssz_fixed_len() -> bool {
417        true
418    }
419
420    fn ssz_fixed_len() -> usize {
421        20
422    }
423
424    fn ssz_bytes_len(&self) -> usize {
425        20
426    }
427
428    fn ssz_append(&self, buf: &mut Vec<u8>) {
429        buf.extend_from_slice(self.as_slice());
430    }
431}
432
433impl<const N: usize> Encode for FixedBytes<N> {
434    #[inline]
435    fn is_ssz_fixed_len() -> bool {
436        true
437    }
438
439    #[inline]
440    fn ssz_bytes_len(&self) -> usize {
441        N
442    }
443
444    #[inline]
445    fn ssz_fixed_len() -> usize {
446        N
447    }
448
449    #[inline]
450    fn ssz_append(&self, buf: &mut Vec<u8>) {
451        buf.extend_from_slice(&self.0);
452    }
453
454    #[inline]
455    fn as_ssz_bytes(&self) -> Vec<u8> {
456        self.0.to_vec()
457    }
458}
459
460impl Encode for Bloom {
461    #[inline]
462    fn is_ssz_fixed_len() -> bool {
463        true
464    }
465
466    #[inline]
467    fn ssz_bytes_len(&self) -> usize {
468        256
469    }
470
471    #[inline]
472    fn ssz_fixed_len() -> usize {
473        256
474    }
475
476    #[inline]
477    fn ssz_append(&self, buf: &mut Vec<u8>) {
478        buf.extend_from_slice(&self.0 .0);
479    }
480
481    #[inline]
482    fn as_ssz_bytes(&self) -> Vec<u8> {
483        self.0.to_vec()
484    }
485}
486
487impl Encode for Bytes {
488    #[inline]
489    fn is_ssz_fixed_len() -> bool {
490        false
491    }
492
493    #[inline]
494    fn ssz_bytes_len(&self) -> usize {
495        self.0.len()
496    }
497
498    #[inline]
499    fn ssz_append(&self, buf: &mut Vec<u8>) {
500        buf.extend_from_slice(&self.0);
501    }
502
503    #[inline]
504    fn as_ssz_bytes(&self) -> Vec<u8> {
505        self.0.to_vec()
506    }
507}
508
509impl Encode for U256 {
510    fn is_ssz_fixed_len() -> bool {
511        true
512    }
513
514    fn ssz_fixed_len() -> usize {
515        32
516    }
517
518    fn ssz_bytes_len(&self) -> usize {
519        32
520    }
521
522    fn ssz_append(&self, buf: &mut Vec<u8>) {
523        buf.extend_from_slice(self.as_le_slice());
524    }
525}
526
527impl Encode for U128 {
528    fn is_ssz_fixed_len() -> bool {
529        true
530    }
531
532    fn ssz_fixed_len() -> usize {
533        16
534    }
535
536    fn ssz_bytes_len(&self) -> usize {
537        16
538    }
539
540    fn ssz_append(&self, buf: &mut Vec<u8>) {
541        buf.extend_from_slice(self.as_le_slice());
542    }
543}
544
545impl<const N: usize> Encode for [u8; N] {
546    fn is_ssz_fixed_len() -> bool {
547        true
548    }
549
550    fn ssz_fixed_len() -> usize {
551        N
552    }
553
554    fn ssz_bytes_len(&self) -> usize {
555        N
556    }
557
558    fn ssz_append(&self, buf: &mut Vec<u8>) {
559        buf.extend_from_slice(&self[..]);
560    }
561}
562
563#[cfg(test)]
564mod tests {
565    use super::*;
566    use alloy_primitives::B256;
567
568    #[test]
569    fn vec_of_u8() {
570        let vec: Vec<u8> = vec![];
571        assert_eq!(vec.as_ssz_bytes(), Vec::<u8>::new());
572
573        let vec: Vec<u8> = vec![1];
574        assert_eq!(vec.as_ssz_bytes(), vec![1]);
575
576        let vec: Vec<u8> = vec![0, 1, 2, 3];
577        assert_eq!(vec.as_ssz_bytes(), vec![0, 1, 2, 3]);
578    }
579
580    #[test]
581    fn vec_of_vec_of_u8() {
582        let vec: Vec<Vec<u8>> = vec![];
583        assert_eq!(vec.as_ssz_bytes(), Vec::<u8>::new());
584
585        let vec: Vec<Vec<u8>> = vec![vec![]];
586        assert_eq!(vec.as_ssz_bytes(), vec![4, 0, 0, 0]);
587
588        let vec: Vec<Vec<u8>> = vec![vec![], vec![]];
589        assert_eq!(vec.as_ssz_bytes(), vec![8, 0, 0, 0, 8, 0, 0, 0]);
590
591        let vec: Vec<Vec<u8>> = vec![vec![0, 1, 2], vec![11, 22, 33]];
592        assert_eq!(
593            vec.as_ssz_bytes(),
594            vec![8, 0, 0, 0, 11, 0, 0, 0, 0, 1, 2, 11, 22, 33]
595        );
596    }
597
598    #[test]
599    fn ssz_encode_u8() {
600        assert_eq!(0_u8.as_ssz_bytes(), vec![0]);
601        assert_eq!(1_u8.as_ssz_bytes(), vec![1]);
602        assert_eq!(100_u8.as_ssz_bytes(), vec![100]);
603        assert_eq!(255_u8.as_ssz_bytes(), vec![255]);
604    }
605
606    #[test]
607    fn ssz_encode_u16() {
608        assert_eq!(1_u16.as_ssz_bytes(), vec![1, 0]);
609        assert_eq!(100_u16.as_ssz_bytes(), vec![100, 0]);
610        assert_eq!((1_u16 << 8).as_ssz_bytes(), vec![0, 1]);
611        assert_eq!(65535_u16.as_ssz_bytes(), vec![255, 255]);
612    }
613
614    #[test]
615    fn ssz_encode_u32() {
616        assert_eq!(1_u32.as_ssz_bytes(), vec![1, 0, 0, 0]);
617        assert_eq!(100_u32.as_ssz_bytes(), vec![100, 0, 0, 0]);
618        assert_eq!((1_u32 << 16).as_ssz_bytes(), vec![0, 0, 1, 0]);
619        assert_eq!((1_u32 << 24).as_ssz_bytes(), vec![0, 0, 0, 1]);
620        assert_eq!((!0_u32).as_ssz_bytes(), vec![255, 255, 255, 255]);
621    }
622
623    #[test]
624    fn ssz_encode_u64() {
625        assert_eq!(1_u64.as_ssz_bytes(), vec![1, 0, 0, 0, 0, 0, 0, 0]);
626        assert_eq!(
627            (!0_u64).as_ssz_bytes(),
628            vec![255, 255, 255, 255, 255, 255, 255, 255]
629        );
630    }
631
632    #[test]
633    fn ssz_encode_u128() {
634        assert_eq!(
635            1_u128.as_ssz_bytes(),
636            vec![1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
637        );
638        assert_eq!(
639            (!0_u128).as_ssz_bytes(),
640            vec![255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
641        );
642    }
643
644    #[test]
645    fn ssz_encode_usize() {
646        assert_eq!(1_usize.as_ssz_bytes(), vec![1, 0, 0, 0, 0, 0, 0, 0]);
647        assert_eq!(
648            (!0_usize).as_ssz_bytes(),
649            vec![255, 255, 255, 255, 255, 255, 255, 255]
650        );
651    }
652
653    #[test]
654    fn ssz_encode_option_u8() {
655        let opt: Option<u8> = None;
656        assert_eq!(opt.as_ssz_bytes(), vec![0]);
657        let opt: Option<u8> = Some(2);
658        assert_eq!(opt.as_ssz_bytes(), vec![1, 2]);
659    }
660
661    #[test]
662    fn ssz_encode_bool() {
663        assert_eq!(true.as_ssz_bytes(), vec![1]);
664        assert_eq!(false.as_ssz_bytes(), vec![0]);
665    }
666
667    #[test]
668    fn ssz_encode_b256() {
669        assert_eq!(B256::from(&[0; 32]).as_ssz_bytes(), vec![0; 32]);
670        assert_eq!(B256::from(&[1; 32]).as_ssz_bytes(), vec![1; 32]);
671
672        let bytes = vec![
673            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
674            0, 0, 0,
675        ];
676
677        assert_eq!(B256::from_slice(&bytes).as_ssz_bytes(), bytes);
678    }
679
680    #[test]
681    fn ssz_encode_u8_array_4() {
682        assert_eq!([0, 0, 0, 0].as_ssz_bytes(), vec![0; 4]);
683        assert_eq!([1, 0, 0, 0].as_ssz_bytes(), vec![1, 0, 0, 0]);
684        assert_eq!([1, 2, 3, 4].as_ssz_bytes(), vec![1, 2, 3, 4]);
685    }
686
687    #[test]
688    fn tuple() {
689        assert_eq!((10u8, 11u8).as_ssz_bytes(), vec![10, 11]);
690        assert_eq!((10u32, 11u8).as_ssz_bytes(), vec![10, 0, 0, 0, 11]);
691        assert_eq!((10u8, 11u8, 12u8).as_ssz_bytes(), vec![10, 11, 12]);
692    }
693}