1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//! CairoType implementation for tuples.
use crate::cairo_types::{CairoType, Result};
use starknet::core::types::FieldElement;

macro_rules! impl_tuples {
    ($num:expr, $( $ty:ident : $rt:ident : $var:ident : $no:tt ),+ $(,)?) => {
        impl<$( $ty, $rt ),+> CairoType for ($( $ty, )+)
        where
            $($ty: CairoType<RustType = $rt>,)+
        {
            type RustType = ($( $rt ),*);

            const SERIALIZED_SIZE: Option<usize> = None;

            #[inline]
            fn serialized_size(rust: &Self::RustType) -> usize {
                let mut size = 0;
                $(
                    size += $ty::serialized_size(& rust.$no);
                )*

                size
            }

            fn serialize(rust: &Self::RustType) -> Vec<FieldElement> {
                let mut out: Vec<FieldElement> = vec![];

                $( out.extend($ty::serialize(& rust.$no)); )*

                out
            }

            fn deserialize(felts: &[FieldElement], offset: usize) -> Result<Self::RustType> {
                let mut offset = offset;

                $(
                    let $var : $rt = $ty::deserialize(felts, offset)?;
                    offset += $ty::serialized_size(& $var);
                )*

                // Remove warning.
                let _offset = offset;

                Ok(($( $var ),*))
            }
        }
    }
}

impl_tuples!(2, A:RA:r0:0, B:RB:r1:1);
impl_tuples!(3, A:RA:r0:0, B:RB:r1:1, C:RC:r2:2);
impl_tuples!(4, A:RA:r0:0, B:RB:r1:1, C:RC:r2:2, D:RD:r3:3);
impl_tuples!(5, A:RA:r0:0, B:RB:r1:1, C:RC:r2:2, D:RD:r3:3, E:RE:r4:4);

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_serialize_tuple2() {
        let v = (FieldElement::ONE, 128_u32);
        let felts = <(FieldElement, u32)>::serialize(&v);
        assert_eq!(felts.len(), 2);
        assert_eq!(felts[0], FieldElement::ONE);
        assert_eq!(felts[1], FieldElement::from(128_u32));
    }

    #[test]
    fn test_deserialize_tuple2() {
        let felts = vec![FieldElement::THREE, 99_u32.into()];
        let vals = <(FieldElement, u32)>::deserialize(&felts, 0).unwrap();
        assert_eq!(vals.0, FieldElement::THREE);
        assert_eq!(vals.1, 99_u32);
    }

    #[test]
    fn test_serialize_tuple2_array() {
        let v = (vec![FieldElement::ONE], 128_u32);
        let felts = <(Vec<FieldElement>, u32)>::serialize(&v);
        assert_eq!(felts.len(), 3);
        assert_eq!(felts[0], FieldElement::ONE);
        assert_eq!(felts[1], FieldElement::ONE);
        assert_eq!(felts[2], FieldElement::from(128_u32));
    }

    #[test]
    fn test_deserialize_tuple2_array() {
        let felts = vec![FieldElement::ONE, FieldElement::ONE, 99_u32.into()];
        let vals = <(Vec<FieldElement>, u32)>::deserialize(&felts, 0).unwrap();
        assert_eq!(vals.0, vec![FieldElement::ONE]);
        assert_eq!(vals.1, 99_u32);
    }
}