fuels_types/traits/
parameterize.rs

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