multiversx_sc/io/
arg_nested_tuple.rs1use unwrap_infallible::UnwrapInfallible;
2
3use super::{EndpointDynArgLoader, EndpointSingleArgLoader};
4use crate::{
5 api::{
6 const_handles, EndpointArgumentApi, EndpointArgumentApiImpl, ErrorApi, ErrorApiImpl,
7 ManagedTypeApi, StaticVarApiImpl, VMApi,
8 },
9 codec::{DecodeError, TopDecodeMulti, TopDecodeMultiInput},
10 err_msg,
11 io::{ArgErrorHandler, ArgId},
12 types::{ManagedArgBuffer, ManagedBuffer, ManagedType, ManagedVecRefIterator},
13};
14
15fn init_arguments_static_data<AA>()
20where
21 AA: EndpointArgumentApi + ManagedTypeApi + ErrorApi,
22{
23 AA::static_var_api_impl().set_num_arguments(AA::argument_api_impl().get_num_arguments());
24}
25
26#[inline(never)]
32fn check_num_arguments_eq<AA>(expected: i32)
33where
34 AA: EndpointArgumentApi + ManagedTypeApi + ErrorApi,
35{
36 if AA::argument_api_impl().get_num_arguments() != expected {
37 AA::error_api_impl().signal_error(err_msg::ARG_WRONG_NUMBER.as_bytes());
38 }
39}
40
41#[inline(never)]
47fn check_num_arguments_ge<AA>(expected: i32)
48where
49 AA: EndpointArgumentApi + ManagedTypeApi + ErrorApi,
50{
51 if AA::static_var_api_impl().get_num_arguments() < expected {
52 AA::error_api_impl().signal_error(DecodeError::MULTI_TOO_FEW_ARGS.message_bytes());
53 }
54}
55
56#[inline(never)]
58fn check_no_more_args<AA, L>(loader: L)
59where
60 AA: EndpointArgumentApi + ManagedTypeApi + ErrorApi,
61 L: TopDecodeMultiInput,
62{
63 if loader.has_next() {
64 AA::error_api_impl().signal_error(DecodeError::MULTI_TOO_MANY_ARGS.message_bytes());
65 }
66}
67
68#[inline(never)]
69fn load_single_arg<AA, T>(index: i32, arg_id: ArgId) -> T
70where
71 AA: EndpointArgumentApi + ManagedTypeApi + ErrorApi,
72 T: TopDecodeMulti,
73{
74 let mut arg_loader = EndpointSingleArgLoader::<AA>::new(index);
75 let h = ArgErrorHandler::<AA>::from(arg_id);
76 T::multi_decode_or_handle_err(&mut arg_loader, h).unwrap_infallible()
77}
78
79#[inline(never)]
80fn load_multi_arg<AA, L, T>(loader: &mut L, arg_id: ArgId) -> T
81where
82 AA: EndpointArgumentApi + ManagedTypeApi + ErrorApi,
83 L: TopDecodeMultiInput,
84 T: TopDecodeMulti,
85{
86 let h = ArgErrorHandler::<AA>::from(arg_id);
87 T::multi_decode_or_handle_err(loader, h).unwrap_infallible()
88}
89
90pub trait ArgNestedTuple<AA>
94where
95 AA: EndpointArgumentApi + ManagedTypeApi + ErrorApi,
96{
97 type ArgNames;
98
99 fn check_num_single_args(index: i32);
100 fn next_single_arg(index: i32, arg_names: Self::ArgNames) -> Self;
101 fn next_multi_arg<L: TopDecodeMultiInput>(loader: L, arg_names: Self::ArgNames) -> Self;
102}
103
104impl<AA, Head, Tail> ArgNestedTuple<AA> for (Head, Tail)
105where
106 AA: EndpointArgumentApi + ManagedTypeApi + ErrorApi,
107 Head: TopDecodeMulti,
108 Tail: ArgNestedTuple<AA>,
109{
110 type ArgNames = (&'static str, Tail::ArgNames);
111
112 #[inline(always)]
113 fn check_num_single_args(index: i32) {
114 if Head::IS_SINGLE_VALUE {
115 Tail::check_num_single_args(index + 1);
116 } else {
117 init_arguments_static_data::<AA>();
119
120 check_num_arguments_ge::<AA>(index);
121 }
122 }
123
124 #[inline(always)]
125 fn next_single_arg(index: i32, arg_names: Self::ArgNames) -> Self {
126 if Head::IS_SINGLE_VALUE {
127 let (arg_name, tail_names) = arg_names;
128 let value = load_single_arg::<AA, Head>(index, ArgId::from(arg_name));
129 (value, Tail::next_single_arg(index + 1, tail_names))
130 } else {
131 let loader = EndpointDynArgLoader::<AA>::new_at_index(index);
132 Self::next_multi_arg(loader, arg_names)
133 }
134 }
135
136 #[inline(always)]
137 fn next_multi_arg<L: TopDecodeMultiInput>(mut loader: L, arg_names: Self::ArgNames) -> Self {
138 let (arg_name, tail_names) = arg_names;
139 let value = load_multi_arg::<AA, L, Head>(&mut loader, ArgId::from(arg_name));
140 (value, Tail::next_multi_arg(loader, tail_names))
141 }
142}
143
144impl<AA> ArgNestedTuple<AA> for ()
145where
146 AA: EndpointArgumentApi + ManagedTypeApi + ErrorApi,
147{
148 type ArgNames = ();
149
150 #[inline(always)]
151 fn check_num_single_args(index: i32) {
152 check_num_arguments_eq::<AA>(index);
153 }
154
155 #[inline(always)]
156 fn next_single_arg(_index: i32, _arg_names: Self::ArgNames) -> Self {}
157
158 #[inline(always)]
159 fn next_multi_arg<L: TopDecodeMultiInput>(loader: L, _arg_names: Self::ArgNames) -> Self {
160 check_no_more_args::<AA, L>(loader);
161 }
162}
163
164#[inline(always)]
166pub fn load_endpoint_args<AA, N>(arg_names: N::ArgNames) -> N
167where
168 AA: EndpointArgumentApi + ManagedTypeApi + ErrorApi,
169 N: ArgNestedTuple<AA>,
170{
171 N::check_num_single_args(0);
172 N::next_single_arg(0, arg_names)
173}
174
175#[inline(always)]
176pub fn load_callback_closure_args<AA, N>(arg_names: N::ArgNames) -> N
177where
178 AA: VMApi,
179 N: ArgNestedTuple<AA>,
180{
181 let loader = callback_closure_args_loader::<AA>();
182 N::next_multi_arg(loader, arg_names)
183}
184
185#[inline(always)]
187pub fn load_multi_args_custom_loader<AA, L, N>(loader: L, arg_names: N::ArgNames) -> N
188where
189 AA: EndpointArgumentApi + ManagedTypeApi + ErrorApi,
190 L: TopDecodeMultiInput,
191 N: ArgNestedTuple<AA>,
192{
193 init_arguments_static_data::<AA>();
194 N::next_multi_arg(loader, arg_names)
195}
196
197fn callback_closure_args_loader<AA>() -> ManagedVecRefIterator<'static, AA, ManagedBuffer<AA>>
198where
199 AA: VMApi,
200{
201 let cb_closure_args_serialized = ManagedBuffer::<AA>::new();
202 AA::argument_api_impl().load_callback_closure_buffer(cb_closure_args_serialized.get_handle());
203 unsafe {
204 let mut cb_closure_args_buffer =
205 ManagedArgBuffer::<AA>::from_raw_handle(const_handles::CALLBACK_CLOSURE_ARGS_BUFFER);
206 cb_closure_args_buffer.deserialize_overwrite(cb_closure_args_serialized);
207 ManagedVecRefIterator::new_from_handle(cb_closure_args_buffer.forget_into_handle())
208 }
209}