diff --git a/framework/base/src/io.rs b/framework/base/src/io.rs index be7f4444f6..7d71dd2e27 100644 --- a/framework/base/src/io.rs +++ b/framework/base/src/io.rs @@ -7,7 +7,6 @@ mod arg_nested_tuple; mod bytes_arg_loader; pub mod call_value_init; mod finish; -mod managed_result_arg_loader; mod signal_error; pub use arg_de_input::*; @@ -18,5 +17,4 @@ use arg_loader_single::*; pub use arg_nested_tuple::*; pub use bytes_arg_loader::*; pub use finish::*; -pub use managed_result_arg_loader::*; pub use signal_error::*; diff --git a/framework/base/src/io/arg_nested_tuple.rs b/framework/base/src/io/arg_nested_tuple.rs index 1a0eaace7a..aa833633d8 100644 --- a/framework/base/src/io/arg_nested_tuple.rs +++ b/framework/base/src/io/arg_nested_tuple.rs @@ -1,15 +1,15 @@ use unwrap_infallible::UnwrapInfallible; -use super::{EndpointDynArgLoader, EndpointSingleArgLoader, ManagedResultArgLoader}; +use super::{EndpointDynArgLoader, EndpointSingleArgLoader}; use crate::{ api::{ - const_handles, use_raw_handle, EndpointArgumentApi, EndpointArgumentApiImpl, ErrorApi, - ErrorApiImpl, ManagedTypeApi, StaticVarApiImpl, VMApi, + const_handles, EndpointArgumentApi, EndpointArgumentApiImpl, ErrorApi, ErrorApiImpl, + ManagedTypeApi, StaticVarApiImpl, VMApi, }, codec::{DecodeError, TopDecodeMulti, TopDecodeMultiInput}, err_msg, io::{ArgErrorHandler, ArgId}, - types::{ManagedArgBuffer, ManagedBuffer, ManagedType}, + types::{ManagedArgBuffer, ManagedBuffer, ManagedType, ManagedVecRefIterator}, }; /// Argument count cannot change during execution, and it can get queried multiple times, @@ -194,19 +194,16 @@ where N::next_multi_arg(loader, arg_names) } -fn callback_closure_args_loader() -> ManagedResultArgLoader +fn callback_closure_args_loader() -> ManagedVecRefIterator<'static, AA, ManagedBuffer> where AA: VMApi, { + let cb_closure_args_serialized = ManagedBuffer::::new(); + AA::argument_api_impl().load_callback_closure_buffer(cb_closure_args_serialized.get_handle()); unsafe { - AA::argument_api_impl() - .load_callback_closure_buffer(use_raw_handle(const_handles::MBUF_TEMPORARY_1)); - let cb_closure_args_serialized = - ManagedBuffer::::from_raw_handle(const_handles::MBUF_TEMPORARY_1); let mut cb_closure_args_buffer = ManagedArgBuffer::::from_raw_handle(const_handles::CALLBACK_CLOSURE_ARGS_BUFFER); cb_closure_args_buffer.deserialize_overwrite(cb_closure_args_serialized); - - ManagedResultArgLoader::new(cb_closure_args_buffer.into_vec_of_buffers()) + ManagedVecRefIterator::new_from_handle(cb_closure_args_buffer.forget_into_handle()) } } diff --git a/framework/base/src/io/managed_result_arg_loader.rs b/framework/base/src/io/managed_result_arg_loader.rs deleted file mode 100644 index 77bc9967e1..0000000000 --- a/framework/base/src/io/managed_result_arg_loader.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::codec::{DecodeError, DecodeErrorHandler, TopDecodeMultiInput}; - -use crate::{ - api::{ErrorApi, ManagedTypeApi}, - types::{ManagedBuffer, ManagedVec}, -}; - -pub struct ManagedResultArgLoader -where - A: ManagedTypeApi + ErrorApi, -{ - data: ManagedVec>, - data_len: usize, - next_index: usize, -} - -impl ManagedResultArgLoader -where - A: ManagedTypeApi + ErrorApi, -{ - pub fn new(data: ManagedVec>) -> Self { - let data_len = data.len(); - ManagedResultArgLoader { - data, - data_len, - next_index: 0, - } - } -} - -impl TopDecodeMultiInput for ManagedResultArgLoader -where - A: ManagedTypeApi + ErrorApi, -{ - type ValueInput = ManagedBuffer; - - fn has_next(&self) -> bool { - self.next_index < self.data_len - } - - fn next_value_input(&mut self, h: H) -> Result - where - H: DecodeErrorHandler, - { - if let Some(buffer) = self.data.try_get(self.next_index) { - self.next_index += 1; - Ok((*buffer).clone()) - } else { - Err(h.handle_error(DecodeError::MULTI_TOO_FEW_ARGS)) - } - } -} diff --git a/framework/base/src/types/interaction/callback_closure.rs b/framework/base/src/types/interaction/callback_closure.rs index 6b2b73feee..b7ea4264a8 100644 --- a/framework/base/src/types/interaction/callback_closure.rs +++ b/framework/base/src/types/interaction/callback_closure.rs @@ -9,10 +9,9 @@ use crate::{ }, contract_base::{BlockchainWrapper, ExitCodecErrorHandler, ManagedSerializer}, err_msg, - io::ManagedResultArgLoader, storage::StorageKey, storage_clear, storage_get, storage_set, - types::{ManagedBuffer, ManagedType}, + types::{ManagedBuffer, ManagedType, ManagedVecRefIterator}, }; use super::ManagedArgBuffer; @@ -125,8 +124,8 @@ impl CallbackClosureForDeser { CallbackClosureMatcher::new(&self.callback_name) } - pub fn into_arg_loader(self) -> ManagedResultArgLoader { - ManagedResultArgLoader::new(self.closure_args.data) + pub fn arg_iter(&self) -> ManagedVecRefIterator<'_, M, ManagedBuffer> { + self.closure_args.iter_buffers() } } diff --git a/framework/base/src/types/interaction/callback_selector_result.rs b/framework/base/src/types/interaction/callback_selector_result.rs index d04487b57f..e6bd200a66 100644 --- a/framework/base/src/types/interaction/callback_selector_result.rs +++ b/framework/base/src/types/interaction/callback_selector_result.rs @@ -1,13 +1,13 @@ -use crate::api::{ErrorApi, ManagedTypeApi}; - -use super::CallbackClosureForDeser; - /// Used internally between the `callback` and `callback_selector` methods. /// It is likely to be removed in the future. -pub enum CallbackSelectorResult -where - A: ManagedTypeApi + ErrorApi, -{ +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum CallbackSelectorResult { Processed, - NotProcessed(CallbackClosureForDeser), + NotProcessed, +} + +impl CallbackSelectorResult { + pub fn is_processed(self) -> bool { + matches!(self, CallbackSelectorResult::Processed) + } } diff --git a/framework/base/src/types/interaction/contract_call_legacy/contract_deploy.rs b/framework/base/src/types/interaction/contract_call_legacy/contract_deploy.rs index 6b19010e3d..8b12548b30 100644 --- a/framework/base/src/types/interaction/contract_call_legacy/contract_deploy.rs +++ b/framework/base/src/types/interaction/contract_call_legacy/contract_deploy.rs @@ -9,7 +9,7 @@ use crate::{ api::{BlockchainApiImpl, CallTypeApi}, contract_base::{ExitCodecErrorHandler, SendRawWrapper}, err_msg, - io::{ArgErrorHandler, ArgId, ManagedResultArgLoader}, + io::{ArgErrorHandler, ArgId}, types::{ BigUint, CodeMetadata, ManagedAddress, ManagedArgBuffer, ManagedBuffer, ManagedOption, ManagedVec, @@ -112,7 +112,7 @@ where where RequestedResult: TopDecodeMulti + TypeAbiFrom, { - let mut loader = ManagedResultArgLoader::new(raw_result); + let mut loader = raw_result.into_iter(); let arg_id = ArgId::from(&b"init result"[..]); let h = ArgErrorHandler::::from(arg_id); RequestedResult::multi_decode_or_handle_err(&mut loader, h).unwrap_infallible() diff --git a/framework/base/src/types/interaction/tx_exec.rs b/framework/base/src/types/interaction/tx_exec.rs index 0c200df330..6f4ffc40d3 100644 --- a/framework/base/src/types/interaction/tx_exec.rs +++ b/framework/base/src/types/interaction/tx_exec.rs @@ -15,7 +15,7 @@ use unwrap_infallible::UnwrapInfallible; use crate::{ api::CallTypeApi, - io::{ArgErrorHandler, ArgId, ManagedResultArgLoader}, + io::{ArgErrorHandler, ArgId}, types::{ManagedBuffer, ManagedVec}, }; use multiversx_sc_codec::TopDecodeMulti; @@ -30,7 +30,7 @@ where SA: CallTypeApi + 'static, RequestedResult: TopDecodeMulti, { - let mut loader = ManagedResultArgLoader::new(raw_result); + let mut loader = raw_result.into_iter(); let arg_id = ArgId::from(&b"sync result"[..]); let h: ArgErrorHandler = ArgErrorHandler::::from(arg_id); RequestedResult::multi_decode_or_handle_err(&mut loader, h).unwrap_infallible() diff --git a/framework/base/src/types/managed/multi_value/multi_value_encoded_iter.rs b/framework/base/src/types/managed/multi_value/multi_value_encoded_iter.rs index 4b8db58ffb..670586fbf6 100644 --- a/framework/base/src/types/managed/multi_value/multi_value_encoded_iter.rs +++ b/framework/base/src/types/managed/multi_value/multi_value_encoded_iter.rs @@ -4,10 +4,10 @@ use unwrap_infallible::UnwrapInfallible; use crate::codec::{TopDecodeMulti, TopDecodeMultiInput}; -use crate::types::{ManagedBuffer, ManagedVec}; +use crate::types::{ManagedBuffer, ManagedVec, ManagedVecOwnedIterator}; use crate::{ api::{ErrorApi, ManagedTypeApi}, - io::{ArgErrorHandler, ArgId, ManagedResultArgLoader}, + io::{ArgErrorHandler, ArgId}, }; /// Iterator for `MultiValueEncoded` and `MultiValueEncodedCounted`. @@ -18,7 +18,7 @@ where M: ManagedTypeApi + ErrorApi, T: TopDecodeMulti, { - data_loader: ManagedResultArgLoader, + data_loader: ManagedVecOwnedIterator>, _phantom: PhantomData, } @@ -29,7 +29,7 @@ where { pub(crate) fn new(raw_buffers: ManagedVec>) -> Self { MultiValueEncodedIterator { - data_loader: ManagedResultArgLoader::new(raw_buffers), + data_loader: raw_buffers.into_iter(), _phantom: PhantomData, } } @@ -43,14 +43,13 @@ where type Item = T; fn next(&mut self) -> Option { - if self.data_loader.has_next() { - let arg_id = ArgId::from(&b"var args"[..]); - let h = ArgErrorHandler::::from(arg_id); - let result = - T::multi_decode_or_handle_err(&mut self.data_loader, h).unwrap_infallible(); - Some(result) - } else { - None + if !self.data_loader.has_next() { + return None; } + + let arg_id = ArgId::from(&b"var args"[..]); + let h = ArgErrorHandler::::from(arg_id); + let result = T::multi_decode_or_handle_err(&mut self.data_loader, h).unwrap_infallible(); + Some(result) } } diff --git a/framework/base/src/types/managed/wrapped/managed_vec_iter_owned.rs b/framework/base/src/types/managed/wrapped/managed_vec_iter_owned.rs index 055b4b4a11..f4712e7464 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_iter_owned.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_iter_owned.rs @@ -1,4 +1,9 @@ -use crate::{api::ManagedTypeApi, types::ManagedType}; +use multiversx_sc_codec::{DecodeError, DecodeErrorHandler, TopDecodeMultiInput}; + +use crate::{ + api::{ErrorApi, ManagedTypeApi}, + types::{ManagedBuffer, ManagedType}, +}; use super::{ManagedVec, ManagedVecItem, ManagedVecPayloadIterator}; @@ -34,6 +39,10 @@ where } } } + + pub(crate) fn iter_is_empty(&self) -> bool { + self.payload_iter.iter_is_empty() + } } impl Iterator for ManagedVecOwnedIterator @@ -70,3 +79,25 @@ where Some(T::read_from_payload(&payload)) } } + +impl TopDecodeMultiInput for ManagedVecOwnedIterator> +where + A: ManagedTypeApi + ErrorApi, +{ + type ValueInput = ManagedBuffer; + + fn has_next(&self) -> bool { + !self.iter_is_empty() + } + + fn next_value_input(&mut self, h: H) -> Result + where + H: DecodeErrorHandler, + { + if let Some(buffer) = self.next() { + Ok(buffer) + } else { + Err(h.handle_error(DecodeError::MULTI_TOO_FEW_ARGS)) + } + } +} diff --git a/framework/base/src/types/managed/wrapped/managed_vec_iter_payload.rs b/framework/base/src/types/managed/wrapped/managed_vec_iter_payload.rs index 44293133d2..28fd6e3943 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_iter_payload.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_iter_payload.rs @@ -40,6 +40,15 @@ where _phantom: PhantomData, } } + + pub(crate) fn remaining(&self) -> usize { + (self.byte_end - self.byte_start) / P::payload_size() + } + + /// TODO: can be replaced with ExactSizeIterator::is_empty once it's stabilized + pub(crate) fn iter_is_empty(&self) -> bool { + self.byte_start >= self.byte_end + } } impl Iterator for ManagedVecPayloadIterator @@ -50,10 +59,10 @@ where type Item = P; fn next(&mut self) -> Option

{ - let next_byte_start = self.byte_start + P::payload_size(); - if next_byte_start > self.byte_end { + if self.iter_is_empty() { return None; } + let next_byte_start = self.byte_start + P::payload_size(); let mut payload = P::new_buffer(); let _ = M::managed_type_impl().mb_load_slice( @@ -67,8 +76,7 @@ where } fn size_hint(&self) -> (usize, Option) { - let size = P::payload_size(); - let remaining = (self.byte_end - self.byte_start) / size; + let remaining = self.remaining(); (remaining, Some(remaining)) } } @@ -78,6 +86,9 @@ where M: ManagedTypeApi, P: ManagedVecItemPayload, { + fn len(&self) -> usize { + self.remaining() + } } impl DoubleEndedIterator for ManagedVecPayloadIterator @@ -86,7 +97,7 @@ where P: ManagedVecItemPayload, { fn next_back(&mut self) -> Option { - if self.byte_start + P::payload_size() > self.byte_end { + if self.iter_is_empty() { return None; } self.byte_end -= P::payload_size(); diff --git a/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs b/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs index b57a16d3d7..f48e3ecab1 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs @@ -1,6 +1,11 @@ use core::marker::PhantomData; -use crate::{api::ManagedTypeApi, types::ManagedType}; +use multiversx_sc_codec::{DecodeError, DecodeErrorHandler, TopDecodeMultiInput}; + +use crate::{ + api::{ErrorApi, ManagedTypeApi}, + types::{ManagedBuffer, ManagedType}, +}; use super::{ManagedVec, ManagedVecItem, ManagedVecPayloadIterator}; @@ -30,14 +35,22 @@ where M: ManagedTypeApi, T: ManagedVecItem, { - pub(crate) fn new(managed_vec: &'a ManagedVec) -> Self { + pub(crate) unsafe fn new_from_handle(vec_handle: M::ManagedBufferHandle) -> Self { unsafe { ManagedVecRefIterator { - payload_iter: ManagedVecPayloadIterator::new(managed_vec.get_handle()), + payload_iter: ManagedVecPayloadIterator::new(vec_handle), _phantom: PhantomData, } } } + + pub(crate) fn new(managed_vec: &'a ManagedVec) -> Self { + unsafe { ManagedVecRefIterator::new_from_handle(managed_vec.get_handle()) } + } + + pub(crate) fn iter_is_empty(&self) -> bool { + self.payload_iter.iter_is_empty() + } } impl<'a, M, T> Iterator for ManagedVecRefIterator<'a, M, T> @@ -89,3 +102,25 @@ where } } } + +impl TopDecodeMultiInput for ManagedVecRefIterator<'_, A, ManagedBuffer> +where + A: ManagedTypeApi + ErrorApi, +{ + type ValueInput = ManagedBuffer; + + fn has_next(&self) -> bool { + !self.iter_is_empty() + } + + fn next_value_input(&mut self, h: H) -> Result + where + H: DecodeErrorHandler, + { + if let Some(buffer) = self.next() { + Ok(buffer.clone()) + } else { + Err(h.handle_error(DecodeError::MULTI_TOO_FEW_ARGS)) + } + } +} diff --git a/framework/derive/src/contract_impl.rs b/framework/derive/src/contract_impl.rs index b10d66d3ad..32ee2d76e0 100644 --- a/framework/derive/src/contract_impl.rs +++ b/framework/derive/src/contract_impl.rs @@ -79,7 +79,9 @@ pub fn contract_implementation( #function_selector_body } - fn callback_selector(&mut self, mut ___cb_closure___: multiversx_sc::types::CallbackClosureForDeser) -> multiversx_sc::types::CallbackSelectorResult { + fn callback_selector(&mut self, ___cb_closure___: &multiversx_sc::types::CallbackClosureForDeser) + -> multiversx_sc::types::CallbackSelectorResult + { #callback_selector_body } diff --git a/framework/derive/src/generate/callback_gen.rs b/framework/derive/src/generate/callback_gen.rs index 23a3a56713..e16e6daafa 100644 --- a/framework/derive/src/generate/callback_gen.rs +++ b/framework/derive/src/generate/callback_gen.rs @@ -29,7 +29,7 @@ pub fn generate_callback_selector_and_main( let cb_main_body = quote! { let _ = self::EndpointWrappers::callback_selector( self, - multiversx_sc::types::CallbackClosureForDeser::no_callback(), + &multiversx_sc::types::CallbackClosureForDeser::no_callback(), ); }; (cb_selector_body, cb_main_body) @@ -39,7 +39,7 @@ pub fn generate_callback_selector_and_main( module_calls(contract.supertraits.as_slice()); if match_arms.is_empty() && module_calls.is_empty() { let cb_selector_body = quote! { - multiversx_sc::types::CallbackSelectorResult::NotProcessed(___cb_closure___) + multiversx_sc::types::CallbackSelectorResult::NotProcessed }; let cb_main_body = quote! {}; (cb_selector_body, cb_main_body) @@ -47,8 +47,7 @@ pub fn generate_callback_selector_and_main( let cb_selector_body = callback_selector_body(match_arms, module_calls); let cb_main_body = quote! { if let Some(___cb_closure___) = multiversx_sc::types::CallbackClosureForDeser::storage_load_and_clear::() { - if let multiversx_sc::types::CallbackSelectorResult::NotProcessed(_) = - self::EndpointWrappers::callback_selector(self, ___cb_closure___) { + if !self::EndpointWrappers::callback_selector(self, &___cb_closure___).is_processed() { multiversx_sc::api::ErrorApiImpl::signal_error( &::error_api_impl(), err_msg::CALLBACK_BAD_FUNC.as_bytes(), @@ -79,7 +78,7 @@ fn callback_selector_body( } #(#match_arms)* #(#module_calls)* - multiversx_sc::types::CallbackSelectorResult::NotProcessed(___cb_closure___) + multiversx_sc::types::CallbackSelectorResult::NotProcessed } } @@ -123,13 +122,8 @@ pub fn module_calls(supertraits: &[Supertrait]) -> Vec .map(|supertrait| { let module_path = &supertrait.module_path; quote! { - match #module_path EndpointWrappers::callback_selector(self, ___cb_closure___) { - multiversx_sc::types::CallbackSelectorResult::Processed => { - return multiversx_sc::types::CallbackSelectorResult::Processed; - }, - multiversx_sc::types::CallbackSelectorResult::NotProcessed(recovered_cb_closure) => { - ___cb_closure___ = recovered_cb_closure; - }, + if #module_path EndpointWrappers::callback_selector(self, ___cb_closure___).is_processed() { + return multiversx_sc::types::CallbackSelectorResult::Processed; } } }) diff --git a/framework/derive/src/generate/method_call_gen_arg.rs b/framework/derive/src/generate/method_call_gen_arg.rs index 20550ca024..8c9b7a0aee 100644 --- a/framework/derive/src/generate/method_call_gen_arg.rs +++ b/framework/derive/src/generate/method_call_gen_arg.rs @@ -88,7 +88,7 @@ pub fn load_legacy_cb_closure_args_snippet(m: &Method) -> proc_macro2::TokenStre }); quote! { let #closure_var_names = multiversx_sc::io::load_multi_args_custom_loader::( - ___cb_closure___.into_arg_loader(), + ___cb_closure___.arg_iter(), #closure_var_names_str, ); } diff --git a/framework/scenario/tests/contract_without_macros.rs b/framework/scenario/tests/contract_without_macros.rs index d461adea6d..29189bf898 100644 --- a/framework/scenario/tests/contract_without_macros.rs +++ b/framework/scenario/tests/contract_without_macros.rs @@ -83,9 +83,9 @@ mod module_1 { } fn callback_selector( &mut self, - mut ___cb_closure___: multiversx_sc::types::CallbackClosureForDeser, - ) -> multiversx_sc::types::CallbackSelectorResult { - multiversx_sc::types::CallbackSelectorResult::NotProcessed(___cb_closure___) + ___cb_closure___: &multiversx_sc::types::CallbackClosureForDeser, + ) -> multiversx_sc::types::CallbackSelectorResult { + multiversx_sc::types::CallbackSelectorResult::NotProcessed } } @@ -357,40 +357,25 @@ mod sample_adder { } fn callback_selector( &mut self, - mut ___cb_closure___: multiversx_sc::types::CallbackClosureForDeser, - ) -> multiversx_sc::types::CallbackSelectorResult { + ___cb_closure___: &multiversx_sc::types::CallbackClosureForDeser, + ) -> multiversx_sc::types::CallbackSelectorResult { let ___cb_closure_matcher___ = ___cb_closure___.matcher::<32usize>(); if ___cb_closure_matcher___.matches_empty() { return multiversx_sc::types::CallbackSelectorResult::Processed; } - match super::module_1::EndpointWrappers::callback_selector(self, ___cb_closure___) { - multiversx_sc::types::CallbackSelectorResult::Processed => { - return multiversx_sc::types::CallbackSelectorResult::Processed; - }, - multiversx_sc::types::CallbackSelectorResult::NotProcessed( - recovered_cb_closure, - ) => { - ___cb_closure___ = recovered_cb_closure; - }, - } - match super::module_1::EndpointWrappers::callback_selector(self, ___cb_closure___) { - multiversx_sc::types::CallbackSelectorResult::Processed => { - return multiversx_sc::types::CallbackSelectorResult::Processed; - }, - multiversx_sc::types::CallbackSelectorResult::NotProcessed( - recovered_cb_closure, - ) => { - ___cb_closure___ = recovered_cb_closure; - }, + if super::module_1::EndpointWrappers::callback_selector(self, ___cb_closure___) + .is_processed() + { + return multiversx_sc::types::CallbackSelectorResult::Processed; } - multiversx_sc::types::CallbackSelectorResult::NotProcessed(___cb_closure___) + multiversx_sc::types::CallbackSelectorResult::NotProcessed } fn callback(&mut self) { if let Some(___cb_closure___) = multiversx_sc::types::CallbackClosureForDeser::storage_load_and_clear::() { - if let multiversx_sc::types::CallbackSelectorResult::NotProcessed(_) = - self::EndpointWrappers::callback_selector(self, ___cb_closure___) + if !self::EndpointWrappers::callback_selector(self, &___cb_closure___) + .is_processed() { multiversx_sc::api::ErrorApiImpl::signal_error( &::error_api_impl(),