diff --git a/contracts/feature-tests/basic-features/scenarios/echo_varags_vec_with_counted_pairs.scen.json b/contracts/feature-tests/basic-features/scenarios/echo_varags_vec_with_counted_pairs.scen.json index d391d0e264..9a9b02e781 100644 --- a/contracts/feature-tests/basic-features/scenarios/echo_varags_vec_with_counted_pairs.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/echo_varags_vec_with_counted_pairs.scen.json @@ -63,6 +63,76 @@ "gas": "*", "refund": "*" } + }, + { + "step": "scCall", + "id": "convert1", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "convert_varags_vec_with_counted_pairs_1", + "arguments": [ + "0x68d79a75b4aa11395dd08994855bd1d90b6b7583d7296dca31c2f8f59e0e7a68", + "0x0f", + "2", + "5", + "5", + "4", + "4" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x68d79a75b4aa11395dd08994855bd1d90b6b7583d7296dca31c2f8f59e0e7a68", + "0x0f", + "2", + "5", + "5", + "4", + "4" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "convert2", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "convert_varags_vec_with_counted_pairs_2", + "arguments": [ + "0x68d79a75b4aa11395dd08994855bd1d90b6b7583d7296dca31c2f8f59e0e7a68", + "0x0f", + "2", + "5", + "5", + "4", + "4" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x68d79a75b4aa11395dd08994855bd1d90b6b7583d7296dca31c2f8f59e0e7a68", + "0x0f", + "2", + "5", + "5", + "4", + "4" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } } ] } diff --git a/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json b/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json index 479b8931c3..cf018d4c91 100644 --- a/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json @@ -229,4 +229,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json index 6ee41eaa4d..81ff2d7fda 100644 --- a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json @@ -199,4 +199,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/src/echo_managed.rs b/contracts/feature-tests/basic-features/src/echo_managed.rs index 8073cab4f1..ffabfa5b16 100644 --- a/contracts/feature-tests/basic-features/src/echo_managed.rs +++ b/contracts/feature-tests/basic-features/src/echo_managed.rs @@ -123,4 +123,51 @@ pub trait EchoManagedTypes { > { m } + + #[endpoint] + fn convert_varags_vec_with_counted_pairs_1( + &self, + address_number_pairs: MultiValueEncoded< + MultiValue3>>, + >, + ) -> MultiValueManagedVec< + MultiValue3>>, + > { + let mut result = MultiValueManagedVec::new(); + for triple in address_number_pairs { + let (address, num, counted_lazy) = triple.into_tuple(); + let mut counted_list = MultiValueManagedVecCounted::new(); + for pair in counted_lazy { + counted_list.push(pair); + } + result.push((address, num, counted_list).into()); + } + result + } + + #[endpoint] + fn convert_varags_vec_with_counted_pairs_2( + &self, + address_number_pairs: MultiValueManagedVec< + MultiValue3< + ManagedAddress, + usize, + MultiValueManagedVecCounted>, + >, + >, + ) -> MultiValueEncoded< + MultiValue3>>, + > { + let mut result = MultiValueEncoded::new(); + for triple in address_number_pairs.into_iter() { + let (address, x, counted_list) = triple.into_tuple(); + let mut counted_lazy = MultiValueEncodedCounted::new(); + let v = counted_list.into_vec(); + for pair in &v { + counted_lazy.push(pair); + } + result.push((address, x, counted_lazy).into()); + } + result + } } diff --git a/contracts/feature-tests/basic-features/wasm/src/lib.rs b/contracts/feature-tests/basic-features/wasm/src/lib.rs index 5759d60830..0b60403fe0 100644 --- a/contracts/feature-tests/basic-features/wasm/src/lib.rs +++ b/contracts/feature-tests/basic-features/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 411 +// Endpoints: 413 // Async Callback: 1 -// Total number of exported functions: 413 +// Total number of exported functions: 415 #![no_std] @@ -181,6 +181,8 @@ multiversx_sc_wasm_adapter::endpoints! { echo_varags_managed_sum => echo_varags_managed_sum echo_varags_vec_with_counted => echo_varags_vec_with_counted echo_varags_vec_with_counted_pairs => echo_varags_vec_with_counted_pairs + convert_varags_vec_with_counted_pairs_1 => convert_varags_vec_with_counted_pairs_1 + convert_varags_vec_with_counted_pairs_2 => convert_varags_vec_with_counted_pairs_2 compute_get_values => compute_get_values compute_create_ec => compute_create_ec compute_get_ec_length => compute_get_ec_length diff --git a/data/codec/src/multi_types/multi_value_tuple.rs b/data/codec/src/multi_types/multi_value_tuple.rs index 9ba85834f6..4882978c66 100644 --- a/data/codec/src/multi_types/multi_value_tuple.rs +++ b/data/codec/src/multi_types/multi_value_tuple.rs @@ -55,9 +55,13 @@ macro_rules! multi_value_impls { impl<$($name),+ > TopDecodeMultiLength for $mv_struct<$($name,)+> where - $($name: TopDecodeMulti,)+ + $($name: TopDecodeMulti + TopDecodeMultiLength,)+ { - const LEN: usize = $len; + const LEN: usize = 0 + $( + + <$name as TopDecodeMultiLength>::LEN + )+ + ; } impl<$($name),+ > TopDecodeMulti for $mv_struct<$($name,)+> diff --git a/framework/base/src/types/managed/multi_value/multi_value_managed_vec_counted.rs b/framework/base/src/types/managed/multi_value/multi_value_managed_vec_counted.rs index 60ffb780ee..a46016e69a 100644 --- a/framework/base/src/types/managed/multi_value/multi_value_managed_vec_counted.rs +++ b/framework/base/src/types/managed/multi_value/multi_value_managed_vec_counted.rs @@ -89,6 +89,30 @@ where } } +impl ManagedVecItem for MultiValueManagedVecCounted +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + type PAYLOAD = as ManagedVecItem>::PAYLOAD; + const SKIPS_RESERIALIZATION: bool = false; + type Ref<'a> = Self; + + fn from_byte_reader(reader: Reader) -> Self { + Self::from(ManagedVec::::from_byte_reader(reader)) + } + + unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( + reader: Reader, + ) -> Self::Ref<'a> { + Self::from_byte_reader(reader) + } + + fn into_byte_writer R>(self, writer: Writer) -> R { + self.contents.into_byte_writer(writer) + } +} + impl TopEncodeMulti for MultiValueManagedVecCounted where M: ManagedTypeApi, diff --git a/framework/base/src/types/managed/wrapped/managed_vec_item.rs b/framework/base/src/types/managed/wrapped/managed_vec_item.rs index 8e7dc5512a..9c85a1d713 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_item.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_item.rs @@ -1,6 +1,7 @@ use core::borrow::Borrow; use multiversx_chain_core::types::{EsdtLocalRole, EsdtTokenType}; +use multiversx_sc_codec::multi_types::{MultiValue2, MultiValue3}; use crate::{ api::ManagedTypeApi, @@ -311,3 +312,126 @@ impl ManagedVecItem for EsdtLocalRole { ::into_byte_writer(self.as_u16(), writer) } } + +impl ManagedVecItem for MultiValue2 +where + T1: ManagedVecItem, + T2: ManagedVecItem, + (T1, (T2, ())): ManagedVecItemNestedTuple, +{ + type PAYLOAD = <(T1, (T2, ())) as ManagedVecItemNestedTuple>::PAYLOAD; + const SKIPS_RESERIALIZATION: bool = T1::SKIPS_RESERIALIZATION && T2::SKIPS_RESERIALIZATION; + type Ref<'a> = Self; + + fn from_byte_reader(mut reader: Reader) -> Self { + let mut payload = ::new_buffer(); + let payload_slice = ManagedVecItemPayload::payload_slice_mut(&mut payload); + reader(payload_slice); + let mut index = 0; + + ( + T1::from_byte_reader(|bytes| { + let next_index = index + T1::payload_size(); + bytes.copy_from_slice(&payload_slice[index..next_index]); + index = next_index; + }), + T2::from_byte_reader(|bytes| { + let next_index = index + T2::payload_size(); + bytes.copy_from_slice(&payload_slice[index..next_index]); + index = next_index; + }), + ) + .into() + } + + unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( + reader: Reader, + ) -> Self::Ref<'a> { + Self::from_byte_reader(reader) + } + + fn into_byte_writer R>(self, mut writer: Writer) -> R { + let mut payload = Self::PAYLOAD::new_buffer(); + let payload_slice = ManagedVecItemPayload::payload_slice_mut(&mut payload); + let mut index = 0; + let (t1, t2) = self.into_tuple(); + T1::into_byte_writer(t1, |bytes| { + let next_index = index + T1::payload_size(); + payload_slice[index..next_index].copy_from_slice(bytes); + index = next_index; + }); + T2::into_byte_writer(t2, |bytes| { + let next_index = index + T2::payload_size(); + payload_slice[index..next_index].copy_from_slice(bytes); + index = next_index; + }); + writer(payload_slice) + } +} + +impl ManagedVecItem for MultiValue3 +where + T1: ManagedVecItem, + T2: ManagedVecItem, + T3: ManagedVecItem, + (T1, (T2, (T3, ()))): ManagedVecItemNestedTuple, +{ + type PAYLOAD = <(T1, (T2, (T3, ()))) as ManagedVecItemNestedTuple>::PAYLOAD; + const SKIPS_RESERIALIZATION: bool = T1::SKIPS_RESERIALIZATION && T2::SKIPS_RESERIALIZATION; + type Ref<'a> = Self; + + fn from_byte_reader(mut reader: Reader) -> Self { + let mut payload = ::new_buffer(); + let payload_slice = ManagedVecItemPayload::payload_slice_mut(&mut payload); + reader(payload_slice); + let mut index = 0; + + ( + T1::from_byte_reader(|bytes| { + let next_index = index + T1::payload_size(); + bytes.copy_from_slice(&payload_slice[index..next_index]); + index = next_index; + }), + T2::from_byte_reader(|bytes| { + let next_index = index + T2::payload_size(); + bytes.copy_from_slice(&payload_slice[index..next_index]); + index = next_index; + }), + T3::from_byte_reader(|bytes| { + let next_index = index + T3::payload_size(); + bytes.copy_from_slice(&payload_slice[index..next_index]); + index = next_index; + }), + ) + .into() + } + + unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( + reader: Reader, + ) -> Self::Ref<'a> { + Self::from_byte_reader(reader) + } + + fn into_byte_writer R>(self, mut writer: Writer) -> R { + let mut payload = Self::PAYLOAD::new_buffer(); + let payload_slice = ManagedVecItemPayload::payload_slice_mut(&mut payload); + let mut index = 0; + let (t1, t2, t3) = self.into_tuple(); + T1::into_byte_writer(t1, |bytes| { + let next_index = index + T1::payload_size(); + payload_slice[index..next_index].copy_from_slice(bytes); + index = next_index; + }); + T2::into_byte_writer(t2, |bytes| { + let next_index = index + T2::payload_size(); + payload_slice[index..next_index].copy_from_slice(bytes); + index = next_index; + }); + T3::into_byte_writer(t3, |bytes| { + let next_index = index + T2::payload_size(); + payload_slice[index..next_index].copy_from_slice(bytes); + index = next_index; + }); + writer(payload_slice) + } +} diff --git a/framework/derive/src/managed_vec_item_derive.rs b/framework/derive/src/managed_vec_item_derive.rs index 17c07f21a4..c65a4c9ee3 100644 --- a/framework/derive/src/managed_vec_item_derive.rs +++ b/framework/derive/src/managed_vec_item_derive.rs @@ -186,7 +186,7 @@ fn struct_derive(data_struct: &syn::DataStruct, ast: &syn::DeriveInput) -> Token #(#to_byte_writer_snippets)* - writer(&payload_slice[..]) + writer(payload_slice) } } };