fuels_core/traits/
parameterize.rs

1use fuel_types::{Address, AssetId, ContractId};
2
3use crate::types::{
4    param_types::{EnumVariants, ParamType},
5    AsciiString, Bits256, Bytes, RawSlice, SizedAsciiString,
6};
7
8/// `abigen` requires `Parameterized` to construct nested types. It is also used by `try_from_bytes`
9/// to facilitate the instantiation of custom types from bytes.
10pub trait Parameterize {
11    fn param_type() -> ParamType;
12}
13
14impl Parameterize for Bits256 {
15    fn param_type() -> ParamType {
16        ParamType::B256
17    }
18}
19
20impl Parameterize for RawSlice {
21    fn param_type() -> ParamType {
22        ParamType::RawSlice
23    }
24}
25
26impl<const SIZE: usize, T: Parameterize> Parameterize for [T; SIZE] {
27    fn param_type() -> ParamType {
28        ParamType::Array(Box::new(T::param_type()), SIZE)
29    }
30}
31
32impl<T: Parameterize> Parameterize for Vec<T> {
33    fn param_type() -> ParamType {
34        ParamType::Vector(Box::new(T::param_type()))
35    }
36}
37
38impl Parameterize for Bytes {
39    fn param_type() -> ParamType {
40        ParamType::Bytes
41    }
42}
43
44impl Parameterize for String {
45    fn param_type() -> ParamType {
46        ParamType::String
47    }
48}
49
50impl Parameterize for Address {
51    fn param_type() -> ParamType {
52        ParamType::Struct {
53            name: "Address".to_string(),
54            fields: vec![("0".to_string(), ParamType::B256)],
55            generics: vec![],
56        }
57    }
58}
59
60impl Parameterize for ContractId {
61    fn param_type() -> ParamType {
62        ParamType::Struct {
63            name: "ContractId".to_string(),
64            fields: vec![("0".to_string(), ParamType::B256)],
65            generics: vec![],
66        }
67    }
68}
69
70impl Parameterize for AssetId {
71    fn param_type() -> ParamType {
72        ParamType::Struct {
73            name: "AssetId".to_string(),
74            fields: vec![("0".to_string(), ParamType::B256)],
75            generics: vec![],
76        }
77    }
78}
79
80impl Parameterize for () {
81    fn param_type() -> ParamType {
82        ParamType::Unit
83    }
84}
85
86impl Parameterize for bool {
87    fn param_type() -> ParamType {
88        ParamType::Bool
89    }
90}
91
92impl Parameterize for u8 {
93    fn param_type() -> ParamType {
94        ParamType::U8
95    }
96}
97
98impl Parameterize for u16 {
99    fn param_type() -> ParamType {
100        ParamType::U16
101    }
102}
103
104impl Parameterize for u32 {
105    fn param_type() -> ParamType {
106        ParamType::U32
107    }
108}
109
110impl Parameterize for u64 {
111    fn param_type() -> ParamType {
112        ParamType::U64
113    }
114}
115
116impl Parameterize for u128 {
117    fn param_type() -> ParamType {
118        ParamType::U128
119    }
120}
121
122impl<T> Parameterize for Option<T>
123where
124    T: Parameterize,
125{
126    fn param_type() -> ParamType {
127        let variant_param_types = vec![
128            ("None".to_string(), ParamType::Unit),
129            ("Some".to_string(), T::param_type()),
130        ];
131        let enum_variants = EnumVariants::new(variant_param_types)
132            .expect("should never happen as we provided valid Option param types");
133        ParamType::Enum {
134            name: "Option".to_string(),
135            enum_variants,
136            generics: vec![T::param_type()],
137        }
138    }
139}
140
141impl<T, E> Parameterize for Result<T, E>
142where
143    T: Parameterize,
144    E: Parameterize,
145{
146    fn param_type() -> ParamType {
147        let variant_param_types = vec![
148            ("Ok".to_string(), T::param_type()),
149            ("Err".to_string(), E::param_type()),
150        ];
151        let enum_variants = EnumVariants::new(variant_param_types)
152            .expect("should never happen as we provided valid Result param types");
153        ParamType::Enum {
154            name: "Result".to_string(),
155            enum_variants,
156            generics: vec![T::param_type(), E::param_type()],
157        }
158    }
159}
160
161impl<const LEN: usize> Parameterize for SizedAsciiString<LEN> {
162    fn param_type() -> ParamType {
163        ParamType::StringArray(LEN)
164    }
165}
166
167impl Parameterize for AsciiString {
168    fn param_type() -> ParamType {
169        ParamType::StringSlice
170    }
171}
172
173// Here we implement `Parameterize` for a given tuple of a given length.
174// This is done this way because we can't use `impl<T> Parameterize for (T,)`.
175// So we implement `Parameterize` for each tuple length, covering
176// a reasonable range of tuple lengths.
177macro_rules! impl_parameterize_tuples {
178    ($num: expr, $( $ty: ident : $no: tt, )+) => {
179        impl<$($ty, )+> Parameterize for ($($ty,)+) where
180            $(
181                $ty: Parameterize,
182            )+
183        {
184            fn param_type() -> ParamType {
185                ParamType::Tuple(vec![
186                    $( $ty::param_type(), )+
187                ])
188            }
189
190        }
191    }
192}
193
194// And where we actually implement the `Parameterize` for tuples
195// from size 1 to size 16.
196impl_parameterize_tuples!(1, A:0, );
197impl_parameterize_tuples!(2, A:0, B:1, );
198impl_parameterize_tuples!(3, A:0, B:1, C:2, );
199impl_parameterize_tuples!(4, A:0, B:1, C:2, D:3, );
200impl_parameterize_tuples!(5, A:0, B:1, C:2, D:3, E:4, );
201impl_parameterize_tuples!(6, A:0, B:1, C:2, D:3, E:4, F:5, );
202impl_parameterize_tuples!(7, A:0, B:1, C:2, D:3, E:4, F:5, G:6, );
203impl_parameterize_tuples!(8, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, );
204impl_parameterize_tuples!(9, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, );
205impl_parameterize_tuples!(10, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, );
206impl_parameterize_tuples!(11, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, );
207impl_parameterize_tuples!(12, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, );
208impl_parameterize_tuples!(13, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, );
209impl_parameterize_tuples!(14, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, );
210impl_parameterize_tuples!(15, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, );
211impl_parameterize_tuples!(16, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, );
212
213#[cfg(test)]
214mod tests {
215    use super::*;
216
217    #[test]
218    fn sized_ascii_string_is_parameterized_correctly() {
219        let param_type = SizedAsciiString::<3>::param_type();
220
221        assert!(matches!(param_type, ParamType::StringArray(3)));
222    }
223
224    #[test]
225    fn test_param_type_b256() {
226        assert_eq!(Bits256::param_type(), ParamType::B256);
227    }
228
229    #[test]
230    fn test_param_type_raw_slice() {
231        assert_eq!(RawSlice::param_type(), ParamType::RawSlice);
232    }
233}