multiversx_sc/abi/
type_abi_impl_basic.rs

1use super::*;
2use crate::arrayvec::ArrayVec;
3use alloc::{
4    boxed::Box,
5    format,
6    string::{String, ToString},
7    vec::Vec,
8};
9
10impl TypeAbiFrom<()> for () {}
11
12impl TypeAbi for () {
13    type Unmanaged = Self;
14
15    /// No another exception from the 1-type-1-output-abi rule:
16    /// the unit type produces no output.
17    fn output_abis(_output_names: &[&'static str]) -> OutputAbis {
18        Vec::new()
19    }
20}
21
22impl<T, U> TypeAbiFrom<&U> for &T where T: TypeAbiFrom<U> {}
23
24impl<T: TypeAbi> TypeAbi for &T {
25    type Unmanaged = T::Unmanaged;
26
27    fn type_name() -> TypeName {
28        T::type_name()
29    }
30
31    fn type_name_rust() -> TypeName {
32        T::type_name_rust()
33    }
34
35    fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
36        T::provide_type_descriptions(accumulator);
37    }
38}
39
40impl<T, U> TypeAbiFrom<Box<U>> for Box<T> where T: TypeAbiFrom<U> {}
41
42impl<T: TypeAbi> TypeAbi for Box<T> {
43    type Unmanaged = Self;
44
45    fn type_name() -> TypeName {
46        T::type_name()
47    }
48
49    fn type_name_rust() -> TypeName {
50        format!("Box<{}>", T::type_name_rust())
51    }
52
53    fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
54        T::provide_type_descriptions(accumulator);
55    }
56}
57
58impl<T, U> TypeAbiFrom<&[T]> for &[U] where T: TypeAbiFrom<U> {}
59
60impl<T: TypeAbi> TypeAbi for &[T] {
61    type Unmanaged = Vec<T::Unmanaged>;
62
63    fn type_name() -> TypeName {
64        let t_name = T::type_name();
65        if t_name == "u8" {
66            return "bytes".into();
67        }
68        let mut repr = TypeName::from("List<");
69        repr.push_str(t_name.as_str());
70        repr.push('>');
71        repr
72    }
73
74    fn type_name_rust() -> TypeName {
75        // we need to convert to an owned type
76        format!("Box<[{}]>", T::type_name_rust())
77    }
78
79    fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
80        T::provide_type_descriptions(accumulator);
81    }
82}
83
84impl<T, U> TypeAbiFrom<Vec<T>> for Vec<U> where T: TypeAbiFrom<U> {}
85
86impl<T: TypeAbi> TypeAbi for Vec<T> {
87    type Unmanaged = Vec<T::Unmanaged>;
88
89    fn type_name() -> TypeName {
90        <&[T]>::type_name()
91    }
92
93    fn type_name_rust() -> TypeName {
94        format!("Vec<{}>", T::type_name_rust())
95    }
96
97    fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
98        T::provide_type_descriptions(accumulator);
99    }
100}
101
102impl<T: TypeAbi, const CAP: usize> TypeAbiFrom<ArrayVec<T, CAP>> for ArrayVec<T, CAP> {}
103
104impl<T: TypeAbi, const CAP: usize> TypeAbi for ArrayVec<T, CAP> {
105    type Unmanaged = Self;
106
107    fn type_name() -> TypeName {
108        <&[T]>::type_name()
109    }
110
111    fn type_name_rust() -> TypeName {
112        format!("ArrayVec<{}, {}usize>", T::type_name_rust(), CAP)
113    }
114
115    fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
116        T::provide_type_descriptions(accumulator);
117    }
118}
119
120impl<T> TypeAbiFrom<Box<[T]>> for Box<[T]> {}
121
122impl<T: TypeAbi> TypeAbi for Box<[T]> {
123    type Unmanaged = Self;
124
125    fn type_name() -> TypeName {
126        <&[T]>::type_name()
127    }
128
129    fn type_name_rust() -> TypeName {
130        format!("Box<[{}]>", T::type_name_rust())
131    }
132
133    fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
134        T::provide_type_descriptions(accumulator);
135    }
136}
137
138impl TypeAbiFrom<String> for String {}
139impl TypeAbiFrom<&String> for String {}
140impl TypeAbiFrom<&str> for String {}
141impl TypeAbiFrom<Box<str>> for String {}
142
143impl TypeAbi for String {
144    type Unmanaged = Self;
145
146    fn type_name() -> TypeName {
147        "utf-8 string".into()
148    }
149}
150
151impl TypeAbiFrom<&'static str> for &'static str {}
152
153impl TypeAbi for &'static str {
154    type Unmanaged = Self;
155
156    fn type_name() -> TypeName {
157        String::type_name()
158    }
159
160    fn type_name_rust() -> TypeName {
161        "&'static str".into()
162    }
163}
164
165impl TypeAbiFrom<Box<str>> for Box<str> {}
166impl TypeAbiFrom<&str> for Box<str> {}
167impl TypeAbiFrom<String> for Box<str> {}
168
169impl TypeAbi for Box<str> {
170    type Unmanaged = Self;
171
172    fn type_name() -> TypeName {
173        String::type_name()
174    }
175
176    fn type_name_rust() -> TypeName {
177        "Box<str>".into()
178    }
179}
180
181macro_rules! type_abi_name_only {
182    ($ty:ty, $name:expr) => {
183        impl TypeAbiFrom<$ty> for $ty {}
184        impl TypeAbiFrom<&$ty> for $ty {}
185
186        impl TypeAbi for $ty {
187            type Unmanaged = Self;
188
189            fn type_name() -> TypeName {
190                TypeName::from($name)
191            }
192
193            fn provide_type_descriptions<TDC: TypeDescriptionContainer>(_: &mut TDC) {}
194        }
195    };
196}
197
198type_abi_name_only!(u8, "u8");
199type_abi_name_only!(u16, "u16");
200type_abi_name_only!(u32, "u32");
201type_abi_name_only!(usize, "u32");
202type_abi_name_only!(u64, "u64");
203type_abi_name_only!(u128, "u128");
204
205type_abi_name_only!(i8, "i8");
206type_abi_name_only!(i16, "i16");
207type_abi_name_only!(i32, "i32");
208type_abi_name_only!(isize, "i32");
209type_abi_name_only!(i64, "i64");
210
211type_abi_name_only!(core::num::NonZeroUsize, "NonZeroUsize");
212type_abi_name_only!(bool, "bool");
213type_abi_name_only!(f64, "f64");
214
215// Unsigned integer types: the contract can return a smaller capacity result and and we can interpret it as a larger capacity type.
216
217impl TypeAbiFrom<u64> for u128 {}
218impl TypeAbiFrom<usize> for u128 {}
219impl TypeAbiFrom<u32> for u128 {}
220impl TypeAbiFrom<u16> for u128 {}
221impl TypeAbiFrom<u8> for u128 {}
222
223impl TypeAbiFrom<usize> for u64 {}
224impl TypeAbiFrom<u32> for u64 {}
225impl TypeAbiFrom<u16> for u64 {}
226impl TypeAbiFrom<u8> for u64 {}
227
228impl TypeAbiFrom<usize> for u32 {}
229impl TypeAbiFrom<u16> for u32 {}
230impl TypeAbiFrom<u8> for u32 {}
231
232impl TypeAbiFrom<u32> for usize {}
233impl TypeAbiFrom<u16> for usize {}
234impl TypeAbiFrom<u8> for usize {}
235
236impl TypeAbiFrom<u8> for u16 {}
237
238// Signed, the same.
239
240impl TypeAbiFrom<isize> for i64 {}
241impl TypeAbiFrom<i32> for i64 {}
242impl TypeAbiFrom<i16> for i64 {}
243impl TypeAbiFrom<i8> for i64 {}
244
245impl TypeAbiFrom<isize> for i32 {}
246impl TypeAbiFrom<i16> for i32 {}
247impl TypeAbiFrom<i8> for i32 {}
248
249impl TypeAbiFrom<i32> for isize {}
250impl TypeAbiFrom<i16> for isize {}
251impl TypeAbiFrom<i8> for isize {}
252
253impl TypeAbiFrom<i8> for i16 {}
254
255impl<T, U> TypeAbiFrom<Option<U>> for Option<T> where T: TypeAbiFrom<U> {}
256
257impl<T> TypeAbi for Option<T>
258where
259    T: TypeAbi,
260{
261    type Unmanaged = Option<T::Unmanaged>;
262
263    fn type_name() -> TypeName {
264        format!("Option<{}>", T::type_name())
265    }
266
267    fn type_name_rust() -> TypeName {
268        format!("Option<{}>", T::type_name_rust())
269    }
270
271    fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
272        T::provide_type_descriptions(accumulator);
273    }
274}
275
276impl<T: TypeAbi, E> TypeAbiFrom<Self> for Result<T, E> {}
277
278impl<T: TypeAbi, E> TypeAbi for Result<T, E> {
279    type Unmanaged = Result<T::Unmanaged, E>;
280
281    fn type_name() -> TypeName {
282        T::type_name()
283    }
284
285    fn type_name_rust() -> TypeName {
286        format!(
287            "Result<{}, {}>",
288            T::type_name_rust(),
289            core::any::type_name::<E>()
290        )
291    }
292
293    /// Similar to the SCResult implementation.
294    fn output_abis(output_names: &[&'static str]) -> OutputAbis {
295        T::output_abis(output_names)
296    }
297
298    fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
299        T::provide_type_descriptions(accumulator);
300    }
301}
302
303macro_rules! tuple_impls {
304    ($($len:expr => ($($n:tt $name:ident)+))+) => {
305        $(
306            impl<$($name),+> TypeAbiFrom<Self> for ($($name,)+)
307            where
308                $($name: TypeAbi,)+
309            {}
310
311            impl<$($name),+> TypeAbi for ($($name,)+)
312            where
313                $($name: TypeAbi,)+
314            {
315                type Unmanaged = ($($name::Unmanaged,)+);
316
317                fn type_name() -> TypeName {
318                    let mut repr = TypeName::from("tuple<");
319                    $(
320                        if $n > 0 {
321                            repr.push(',');
322                        }
323                        repr.push_str($name::type_name().as_str());
324                    )+
325                    repr.push('>');
326                    repr
327                }
328
329                fn type_name_rust() -> TypeName {
330                    let mut repr = TypeName::from("(");
331                    $(
332                        if $n > 0 {
333                            repr.push_str(", ");
334                        }
335                        repr.push_str($name::type_name_rust().as_str());
336                    )+
337                    repr.push(')');
338                    repr
339                }
340
341                fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
342                    $(
343                        $name::provide_type_descriptions(accumulator);
344                    )+
345                }
346            }
347        )+
348    }
349}
350
351tuple_impls! {
352    1  => (0 T0)
353    2  => (0 T0 1 T1)
354    3  => (0 T0 1 T1 2 T2)
355    4  => (0 T0 1 T1 2 T2 3 T3)
356    5  => (0 T0 1 T1 2 T2 3 T3 4 T4)
357    6  => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
358    7  => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
359    8  => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
360    9  => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
361    10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
362    11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
363    12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
364    13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
365    14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
366    15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
367    16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
368}
369
370impl<T, U, const N: usize> TypeAbiFrom<[U; N]> for [T; N] where T: TypeAbiFrom<U> {}
371
372impl<T: TypeAbi, const N: usize> TypeAbi for [T; N] {
373    type Unmanaged = [T::Unmanaged; N];
374
375    fn type_name() -> TypeName {
376        let mut repr = TypeName::from("array");
377        repr.push_str(N.to_string().as_str());
378        repr.push('<');
379        repr.push_str(T::type_name().as_str());
380        repr.push('>');
381        repr
382    }
383
384    fn type_name_rust() -> TypeName {
385        let mut repr = TypeName::from("[");
386        repr.push_str(T::type_name_rust().as_str());
387        repr.push_str("; ");
388        repr.push_str(N.to_string().as_str());
389        repr.push(']');
390        repr
391    }
392
393    fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
394        T::provide_type_descriptions(accumulator);
395    }
396}