multiversx_sc/abi/
type_abi.rs

1use super::*;
2use alloc::{format, string::ToString, vec::Vec};
3
4/// Implemented for all types that can end up in the ABI:
5/// - argument types,
6/// - result types,
7/// - event log arguments
8/// - etc.
9///
10/// Will be automatically implemented for struct ad enum types via the `#[type_abi]` annotation.
11pub trait TypeAbi: TypeAbiFrom<Self> {
12    type Unmanaged;
13
14    fn type_names() -> TypeNames {
15        TypeNames {
16            abi: Self::type_name(),
17            rust: Self::type_name_rust(),
18        }
19    }
20
21    fn type_name() -> TypeName {
22        core::any::type_name::<Self>().into()
23    }
24
25    fn type_name_rust() -> TypeName {
26        core::any::type_name::<Self>().into()
27    }
28
29    /// A type can provide more than its own name.
30    /// For instance, a struct can also provide the descriptions of the type of its fields.
31    /// TypeAbi doesn't care for the exact accumulator type,
32    /// which is abstracted by the TypeDescriptionContainer trait.
33    fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
34        let type_names = Self::type_names();
35        accumulator.insert(
36            type_names,
37            TypeDescription {
38                docs: Vec::new(),
39                names: Self::type_names(),
40                contents: TypeContents::NotSpecified,
41                macro_attributes: Vec::new(),
42            },
43        );
44    }
45
46    #[doc(hidden)]
47    fn is_variadic() -> bool {
48        false
49    }
50
51    /// Method that provides output ABIs directly.
52    /// All types should return a single output, since Rust only allows for single method results
53    /// (even if it is a multi-output, live MultiResultVec),
54    /// however, MultiResultX when top-level can be seen as multiple endpoint results.
55    /// This method gives it an opportunity to dissolve into its components.
56    /// Should only be overridden by framework types.
57    /// Output names are optionally provided in contracts via the `output_name` method attribute.
58    #[doc(hidden)]
59    fn output_abis(output_names: &[&'static str]) -> OutputAbis {
60        let mut result = Vec::with_capacity(1);
61        let output_name = if !output_names.is_empty() {
62            output_names[0]
63        } else {
64            ""
65        };
66        result.push(OutputAbi {
67            output_name: output_name.to_string(),
68            type_names: Self::type_names(),
69            multi_result: Self::is_variadic(),
70        });
71        result
72    }
73}
74
75pub fn type_name_variadic<T: TypeAbi>() -> TypeName {
76    format!("variadic<{}>", T::type_name())
77}
78
79pub fn type_name_multi_value_encoded<T: TypeAbi>() -> TypeName {
80    format!("MultiValueEncoded<$API, {}>", T::type_name_rust())
81}
82
83pub fn type_name_optional<T: TypeAbi>() -> TypeName {
84    let mut repr = TypeName::from("optional<");
85    repr.push_str(T::type_name().as_str());
86    repr.push('>');
87    repr
88}