1use multiversx_sc_codec::MultiValueLength;
2use multiversx_sc_codec::multi_types::MultiValue3;
3use unwrap_infallible::UnwrapInfallible;
4
5use crate::codec::multi_types::MultiValueVec;
6use crate::types::{
7 BigUint, EgldOrEsdtTokenIdentifier, EgldOrEsdtTokenPayment, EgldOrEsdtTokenPaymentMultiValue,
8 EsdtTokenIdentifier, EsdtTokenPayment, NonZeroBigUint, Payment, PaymentMultiValue, TokenId,
9};
10use crate::{
11 abi::{TypeAbi, TypeAbiFrom, TypeDescriptionContainer, TypeName},
12 api::{ErrorApi, ManagedTypeApi},
13 codec::{
14 DecodeErrorHandler, EncodeErrorHandler, MultiValueConstLength, TopDecode, TopDecodeMulti,
15 TopDecodeMultiInput, TopEncode, TopEncodeMulti, TopEncodeMultiOutput,
16 try_cast_execute_or_else,
17 },
18 contract_base::{ExitCodecErrorHandler, ManagedSerializer},
19 err_msg,
20 types::{ManagedArgBuffer, ManagedBuffer, ManagedType, ManagedVec, ManagedVecItem},
21};
22use core::{iter::FromIterator, marker::PhantomData};
23
24use super::MultiValueEncodedIterator;
25
26#[derive(Clone, Default, Debug, PartialEq)]
38pub struct MultiValueEncoded<M, T>
39where
40 M: ManagedTypeApi,
41{
42 pub(super) raw_buffers: ManagedVec<M, ManagedBuffer<M>>,
43 _phantom: PhantomData<T>,
44}
45
46#[deprecated(
47 since = "0.29.0",
48 note = "Alias kept for backwards compatibility. Replace with `MultiValueEncoded`"
49)]
50pub type ManagedVarArgs<M, T> = MultiValueEncoded<M, T>;
51
52#[deprecated(
53 since = "0.29.0",
54 note = "Alias kept for backwards compatibility. Replace with `MultiValueEncoded`"
55)]
56pub type ManagedMultiResultVec<M, T> = MultiValueEncoded<M, T>;
57
58impl<M, T> MultiValueEncoded<M, T>
59where
60 M: ManagedTypeApi,
61{
62 #[inline]
63 fn from_raw_vec(raw_buffers: ManagedVec<M, ManagedBuffer<M>>) -> Self {
64 MultiValueEncoded {
65 raw_buffers,
66 _phantom: PhantomData,
67 }
68 }
69
70 #[inline]
71 pub fn new() -> Self {
72 MultiValueEncoded::from_raw_vec(ManagedVec::new())
73 }
74}
75
76impl<M, T> MultiValueEncoded<M, T>
77where
78 M: ManagedTypeApi + ErrorApi,
79 T: TopEncodeMulti,
80{
81 pub fn push(&mut self, item: T) {
82 item.multi_encode_or_handle_err(
83 &mut self.raw_buffers,
84 ExitCodecErrorHandler::<M>::from(err_msg::SERIALIZER_ENCODE_ERROR),
85 )
86 .unwrap_infallible()
87 }
88}
89
90impl<M, T> From<ManagedVec<M, T>> for MultiValueEncoded<M, T>
91where
92 M: ManagedTypeApi,
93 T: ManagedVecItem + TopEncode + 'static,
94{
95 #[inline]
96 fn from(v: ManagedVec<M, T>) -> Self {
97 try_cast_execute_or_else(
98 v,
99 MultiValueEncoded::from_raw_vec,
100 MultiValueEncoded::from_iter,
101 )
102 }
103}
104
105impl<M, T> MultiValueEncoded<M, T>
106where
107 M: ManagedTypeApi,
108{
109 pub fn to_arg_buffer(&self) -> ManagedArgBuffer<M> {
110 unsafe { ManagedArgBuffer::from_handle(self.raw_buffers.get_handle()) }
111 }
112}
113
114impl<M> MultiValueEncoded<M, ManagedBuffer<M>>
115where
116 M: ManagedTypeApi,
117{
118 pub fn into_vec_of_buffers(self) -> ManagedVec<M, ManagedBuffer<M>> {
119 self.raw_buffers
120 }
121}
122
123impl<M, T> MultiValueEncoded<M, T>
124where
125 M: ManagedTypeApi + ErrorApi,
126{
127 #[inline]
133 pub fn raw_len(&self) -> usize {
134 self.raw_buffers.len()
135 }
136
137 pub fn is_empty(&self) -> bool {
138 self.raw_buffers.is_empty()
139 }
140}
141
142impl<M, T> IntoIterator for MultiValueEncoded<M, T>
143where
144 M: ManagedTypeApi + ErrorApi,
145 T: TopDecodeMulti,
146{
147 type Item = T;
148 type IntoIter = MultiValueEncodedIterator<M, T>;
149 fn into_iter(self) -> Self::IntoIter {
150 MultiValueEncodedIterator::new(self.raw_buffers)
151 }
152}
153
154impl<M, T> MultiValueLength for MultiValueEncoded<M, T>
155where
156 M: ManagedTypeApi + ErrorApi,
157 T: MultiValueConstLength,
158{
159 #[inline]
160 fn multi_value_len(&self) -> usize {
161 self.raw_len()
162 }
163}
164
165impl<M, T> MultiValueEncoded<M, T>
166where
167 M: ManagedTypeApi + ErrorApi,
168 T: MultiValueConstLength,
169{
170 #[inline]
172 pub fn len(&self) -> usize {
173 self.raw_len() / T::MULTI_VALUE_CONST_LEN
174 }
175}
176
177impl<M, T> MultiValueEncoded<M, T>
178where
179 M: ManagedTypeApi + ErrorApi,
180 T: ManagedVecItem + TopDecode,
181{
182 pub fn to_vec(&self) -> ManagedVec<M, T> {
183 let mut result = ManagedVec::new();
184 let serializer = ManagedSerializer::<M>::new();
185 for item in &self.raw_buffers {
186 result.push(serializer.top_decode_from_managed_buffer(&item));
187 }
188 result
189 }
190}
191
192impl<M> MultiValueEncoded<M, MultiValue3<EgldOrEsdtTokenIdentifier<M>, u64, BigUint<M>>>
193where
194 M: ManagedTypeApi + ErrorApi,
195{
196 pub fn convert_payment_multi_triples(self) -> ManagedVec<M, EgldOrEsdtTokenPayment<M>> {
198 let mut payments_vec = ManagedVec::new();
199
200 for multi_arg in self.into_iter() {
201 let (token_identifier, token_nonce, amount) = multi_arg.into_tuple();
202 let payment = EgldOrEsdtTokenPayment::new(token_identifier, token_nonce, amount);
203
204 payments_vec.push(payment);
205 }
206
207 payments_vec
208 }
209}
210
211impl<M> MultiValueEncoded<M, MultiValue3<EsdtTokenIdentifier<M>, u64, BigUint<M>>>
212where
213 M: ManagedTypeApi + ErrorApi,
214{
215 pub fn convert_payment_multi_triples(self) -> ManagedVec<M, EsdtTokenPayment<M>> {
217 let mut payments_vec = ManagedVec::new();
218
219 for multi_arg in self.into_iter() {
220 let (token_identifier, token_nonce, amount) = multi_arg.into_tuple();
221 let payment = EsdtTokenPayment::new(token_identifier, token_nonce, amount);
222
223 payments_vec.push(payment);
224 }
225
226 payments_vec
227 }
228}
229
230impl<M> MultiValueEncoded<M, MultiValue3<TokenId<M>, u64, NonZeroBigUint<M>>>
231where
232 M: ManagedTypeApi + ErrorApi,
233{
234 pub fn convert_payment_multi_triples(self) -> ManagedVec<M, Payment<M>> {
236 let mut payments_vec = ManagedVec::new();
237
238 for multi_arg in self.into_iter() {
239 let (token_identifier, token_nonce, amount) = multi_arg.into_tuple();
240 let payment = Payment::new(token_identifier, token_nonce, amount);
241
242 payments_vec.push(payment);
243 }
244
245 payments_vec
246 }
247}
248
249impl<M> MultiValueEncoded<M, EgldOrEsdtTokenPaymentMultiValue<M>>
250where
251 M: ManagedTypeApi + ErrorApi,
252{
253 pub fn convert_payment(self) -> ManagedVec<M, EgldOrEsdtTokenPayment<M>> {
255 let mut payments_vec = ManagedVec::new();
256
257 for multi_arg in self.into_iter() {
258 payments_vec.push(multi_arg.into_inner());
259 }
260
261 payments_vec
262 }
263
264 pub fn from_vec(v: ManagedVec<M, EgldOrEsdtTokenPayment<M>>) -> Self {
266 let mut encoded = MultiValueEncoded::new();
267
268 for payment in v {
269 encoded.push(EgldOrEsdtTokenPaymentMultiValue::from(payment));
270 }
271
272 encoded
273 }
274}
275
276impl<M> MultiValueEncoded<M, PaymentMultiValue<M>>
277where
278 M: ManagedTypeApi + ErrorApi,
279{
280 pub fn convert_payment(self) -> ManagedVec<M, Payment<M>> {
282 let mut payments_vec = ManagedVec::new();
283
284 for multi_arg in self.into_iter() {
285 payments_vec.push(multi_arg.into_inner());
286 }
287
288 payments_vec
289 }
290}
291
292impl<M, T> TopEncodeMulti for &MultiValueEncoded<M, T>
293where
294 M: ManagedTypeApi + ErrorApi,
295 T: TopEncodeMulti,
296{
297 fn multi_encode_or_handle_err<O, H>(&self, output: &mut O, h: H) -> Result<(), H::HandledErr>
298 where
299 O: TopEncodeMultiOutput,
300 H: EncodeErrorHandler,
301 {
302 for elem in &self.raw_buffers {
303 elem.multi_encode_or_handle_err(output, h)?;
304 }
305 Ok(())
306 }
307}
308
309impl<M, T> TopEncodeMulti for MultiValueEncoded<M, T>
310where
311 M: ManagedTypeApi + ErrorApi,
312 T: TopEncodeMulti,
313{
314 fn multi_encode_or_handle_err<O, H>(&self, output: &mut O, h: H) -> Result<(), H::HandledErr>
315 where
316 O: TopEncodeMultiOutput,
317 H: EncodeErrorHandler,
318 {
319 (&self).multi_encode_or_handle_err(output, h)
320 }
321}
322
323impl<M, T> TopDecodeMulti for MultiValueEncoded<M, T>
324where
325 M: ManagedTypeApi + ErrorApi,
326 T: TopDecodeMulti,
327{
328 fn multi_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
329 where
330 I: TopDecodeMultiInput,
331 H: DecodeErrorHandler,
332 {
333 let mut raw_buffers = ManagedVec::new();
334 while input.has_next() {
335 raw_buffers.push(input.next_value(h)?);
336 }
337 Ok(Self {
338 raw_buffers,
339 _phantom: PhantomData,
340 })
341 }
342}
343
344impl<M, T> TypeAbiFrom<Self> for MultiValueEncoded<M, T>
345where
346 M: ManagedTypeApi,
347 T: TypeAbi,
348{
349}
350
351impl<M, T> TypeAbiFrom<&Self> for MultiValueEncoded<M, T>
352where
353 M: ManagedTypeApi,
354 T: TypeAbi,
355{
356}
357
358impl<M, T> TypeAbi for MultiValueEncoded<M, T>
359where
360 M: ManagedTypeApi,
361 T: TypeAbi,
362{
363 type Unmanaged = MultiValueVec<T::Unmanaged>;
364
365 fn type_name() -> TypeName {
366 crate::abi::type_name_variadic::<T>()
367 }
368
369 fn type_name_rust() -> TypeName {
370 crate::abi::type_name_multi_value_encoded::<T>()
371 }
372
373 fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
374 T::provide_type_descriptions(accumulator);
375 }
376
377 fn is_variadic() -> bool {
378 true
379 }
380}
381
382impl<M, T, U> TypeAbiFrom<MultiValueVec<T>> for MultiValueEncoded<M, U>
383where
384 M: ManagedTypeApi + ErrorApi,
385 T: TopEncodeMulti,
386 U: TypeAbiFrom<T>,
387{
388}
389
390impl<M, T, U> TypeAbiFrom<MultiValueEncoded<M, T>> for MultiValueVec<U>
391where
392 M: ManagedTypeApi + ErrorApi,
393 T: TopEncodeMulti,
394 U: TypeAbiFrom<T>,
395{
396}
397
398impl<M, V> FromIterator<V> for MultiValueEncoded<M, V>
399where
400 M: ManagedTypeApi,
401 V: TopEncodeMulti,
402{
403 fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
404 let mut result: MultiValueEncoded<M, V> = MultiValueEncoded::new();
405 iter.into_iter().for_each(|f| result.push(f));
406 result
407 }
408}