Skip to content

Commit

Permalink
Merge pull request #1877 from multiversx/payload-refactor
Browse files Browse the repository at this point in the history
ManagedVecItem Payload refactor
  • Loading branch information
andrei-marinica authored Nov 28, 2024
2 parents 5b74562 + cb60d95 commit ff19ae5
Show file tree
Hide file tree
Showing 18 changed files with 432 additions and 470 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,17 @@ impl<M: ManagedTypeApi> ManagedVecItem for EsdtTokenPaymentMultiValue<M> {
const SKIPS_RESERIALIZATION: bool = EsdtTokenPayment::<M>::SKIPS_RESERIALIZATION;
type Ref<'a> = Self;

#[inline]
fn from_byte_reader<Reader: FnMut(&mut [u8])>(reader: Reader) -> Self {
EsdtTokenPayment::from_byte_reader(reader).into()
fn read_from_payload(payload: &Self::PAYLOAD) -> Self {
EsdtTokenPayment::read_from_payload(payload).into()
}

#[inline]
unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>(
reader: Reader,
) -> Self::Ref<'a> {
Self::from_byte_reader(reader)
unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> {
// TODO: managed ref
Self::read_from_payload(payload)
}

#[inline]
fn into_byte_writer<R, Writer: FnMut(&[u8]) -> R>(self, writer: Writer) -> R {
self.obj.into_byte_writer(writer)
fn save_to_payload(self, payload: &mut Self::PAYLOAD) {
self.obj.save_to_payload(payload);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,16 @@ where
const SKIPS_RESERIALIZATION: bool = false;
type Ref<'a> = Self;

fn from_byte_reader<Reader: FnMut(&mut [u8])>(reader: Reader) -> Self {
Self::from(ManagedVec::<M, T>::from_byte_reader(reader))
fn read_from_payload(payload: &Self::PAYLOAD) -> Self {
Self::from(ManagedVec::<M, T>::read_from_payload(payload))
}

unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>(
reader: Reader,
) -> Self::Ref<'a> {
Self::from_byte_reader(reader)
unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> {
Self::read_from_payload(payload)
}

fn into_byte_writer<R, Writer: FnMut(&[u8]) -> R>(self, writer: Writer) -> R {
self.contents.into_byte_writer(writer)
fn save_to_payload(self, payload: &mut Self::PAYLOAD) {
self.contents.save_to_payload(payload);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{ManagedVecItem, ManagedVecItemPayload};
use super::ManagedVecItem;
use core::{cmp::Ordering, marker::PhantomData};

pub struct EncodedManagedVecItem<T: ManagedVecItem>
Expand All @@ -14,9 +14,7 @@ where
T: ManagedVecItem,
{
pub(crate) fn decode(&self) -> T {
T::from_byte_reader(|item_bytes| {
item_bytes.copy_from_slice(self.encoded.payload_slice());
})
T::read_from_payload(&self.encoded)
}
}

Expand Down
66 changes: 20 additions & 46 deletions framework/base/src/types/managed/wrapped/esdt_token_payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ use crate::{
derive::type_abi,
};

use super::{ManagedVec, ManagedVecItemPayloadBuffer};
use super::{
managed_vec_item_read_from_payload_index, managed_vec_item_save_to_payload_index, ManagedVec,
ManagedVecItemPayloadBuffer,
};

#[type_abi]
#[derive(TopEncode, NestedEncode, Clone, PartialEq, Eq, Debug)]
Expand Down Expand Up @@ -153,28 +156,6 @@ impl<M: ManagedTypeApi> EsdtTokenPayment<M> {
}
}

fn managed_vec_item_from_slice<T>(arr: &[u8], index: &mut usize) -> T
where
T: ManagedVecItem,
{
ManagedVecItem::from_byte_reader(|bytes| {
let size = T::payload_size();
bytes.copy_from_slice(&arr[*index..*index + size]);
*index += size;
})
}

fn managed_vec_item_to_slice<T>(arr: &mut [u8], index: &mut usize, item: T)
where
T: ManagedVecItem,
{
ManagedVecItem::into_byte_writer(item, |bytes| {
let size = T::payload_size();
arr[*index..*index + size].copy_from_slice(bytes);
*index += size;
});
}

impl<M: ManagedTypeApi> IntoMultiValue for EsdtTokenPayment<M> {
type MultiValue = EsdtTokenPaymentMultiValue<M>;

Expand All @@ -189,37 +170,30 @@ impl<M: ManagedTypeApi> ManagedVecItem for EsdtTokenPayment<M> {
const SKIPS_RESERIALIZATION: bool = false;
type Ref<'a> = Self;

fn from_byte_reader<Reader: FnMut(&mut [u8])>(mut reader: Reader) -> Self {
let mut arr: [u8; 16] = [0u8; 16];
reader(&mut arr[..]);
fn read_from_payload(payload: &Self::PAYLOAD) -> Self {
let mut index = 0;

let token_identifier = managed_vec_item_from_slice(&arr, &mut index);
let token_nonce = managed_vec_item_from_slice(&arr, &mut index);
let amount = managed_vec_item_from_slice(&arr, &mut index);

EsdtTokenPayment {
token_identifier,
token_nonce,
amount,
unsafe {
EsdtTokenPayment {
token_identifier: managed_vec_item_read_from_payload_index(payload, &mut index),
token_nonce: managed_vec_item_read_from_payload_index(payload, &mut index),
amount: managed_vec_item_read_from_payload_index(payload, &mut index),
}
}
}

unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>(
reader: Reader,
) -> Self::Ref<'a> {
Self::from_byte_reader(reader)
unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> {
// TODO: managed ref
Self::read_from_payload(payload)
}

fn into_byte_writer<R, Writer: FnMut(&[u8]) -> R>(self, mut writer: Writer) -> R {
let mut arr: [u8; 16] = [0u8; 16];
fn save_to_payload(self, payload: &mut Self::PAYLOAD) {
let mut index = 0;

managed_vec_item_to_slice(&mut arr, &mut index, self.token_identifier);
managed_vec_item_to_slice(&mut arr, &mut index, self.token_nonce);
managed_vec_item_to_slice(&mut arr, &mut index, self.amount);

writer(&arr[..])
unsafe {
managed_vec_item_save_to_payload_index(self.token_identifier, payload, &mut index);
managed_vec_item_save_to_payload_index(self.token_nonce, payload, &mut index);
managed_vec_item_save_to_payload_index(self.amount, payload, &mut index);
}
}
}

Expand Down
16 changes: 8 additions & 8 deletions framework/base/src/types/managed/wrapped/managed_option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use core::marker::PhantomData;

use crate::{
abi::TypeAbiFrom,
api::HandleConstraints,
codec::{
DecodeErrorHandler, EncodeErrorHandler, NestedDecode, NestedDecodeInput, NestedEncode,
NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput,
Expand Down Expand Up @@ -203,19 +204,18 @@ where
const SKIPS_RESERIALIZATION: bool = false;
type Ref<'a> = Self;

fn from_byte_reader<Reader: FnMut(&mut [u8])>(reader: Reader) -> Self {
let handle = T::OwnHandle::from_byte_reader(reader);
fn read_from_payload(payload: &Self::PAYLOAD) -> Self {
let handle = use_raw_handle(i32::read_from_payload(payload));
Self::new_with_handle(handle)
}

unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>(
reader: Reader,
) -> Self::Ref<'a> {
Self::from_byte_reader(reader)
unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> {
// TODO: managed ref
Self::read_from_payload(payload)
}

fn into_byte_writer<R, Writer: FnMut(&[u8]) -> R>(self, writer: Writer) -> R {
<T::OwnHandle as ManagedVecItem>::into_byte_writer(self.handle, writer)
fn save_to_payload(self, payload: &mut Self::PAYLOAD) {
self.handle.get_raw_handle().save_to_payload(payload);
}
}

Expand Down
69 changes: 38 additions & 31 deletions framework/base/src/types/managed/wrapped/managed_vec.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::EncodedManagedVecItem;
use super::{EncodedManagedVecItem, ManagedVecItemPayload};
use crate::{
abi::{TypeAbi, TypeAbiFrom, TypeDescriptionContainer, TypeName},
api::{ErrorApiImpl, InvalidSliceError, ManagedTypeApi},
Expand Down Expand Up @@ -141,15 +141,16 @@ where

pub fn try_get(&self, index: usize) -> Option<T::Ref<'_>> {
let byte_index = index * T::payload_size();
let mut load_result = Ok(());
let result = unsafe {
T::from_byte_reader_as_borrow(|dest_slice| {
load_result = self.buffer.load_slice(byte_index, dest_slice);
})
};
match load_result {
Ok(_) => Some(result),
Err(_) => None,

let mut payload = T::PAYLOAD::new_buffer();
if self
.buffer
.load_slice(byte_index, payload.payload_slice_mut())
.is_ok()
{
unsafe { Some(T::borrow_from_payload(&payload)) }
} else {
None
}
}

Expand Down Expand Up @@ -187,20 +188,22 @@ where

pub(super) unsafe fn get_unsafe(&self, index: usize) -> T {
let byte_index = index * T::payload_size();
let mut load_result = Ok(());
let result = T::from_byte_reader(|dest_slice| {
load_result = self.buffer.load_slice(byte_index, dest_slice);
});

match load_result {
Ok(_) => result,
Err(_) => M::error_api_impl().signal_error(INDEX_OUT_OF_RANGE_MSG),
let mut payload = T::PAYLOAD::new_buffer();
if self
.buffer
.load_slice(byte_index, payload.payload_slice_mut())
.is_err()
{
M::error_api_impl().signal_error(INDEX_OUT_OF_RANGE_MSG);
}
T::read_from_payload(&payload)
}

pub fn set(&mut self, index: usize, item: T) -> Result<(), InvalidSliceError> {
let byte_index = index * T::payload_size();
item.into_byte_writer(|slice| self.buffer.set_slice(byte_index, slice))
let mut payload = T::PAYLOAD::new_buffer();
item.save_to_payload(&mut payload);
self.buffer.set_slice(byte_index, payload.payload_slice())
}

/// Returns a new `ManagedVec`, containing the [start_index, end_index) range of elements.
Expand All @@ -213,9 +216,9 @@ where
}

pub fn push(&mut self, item: T) {
item.into_byte_writer(|bytes| {
self.buffer.append_bytes(bytes);
});
let mut payload = T::PAYLOAD::new_buffer();
item.save_to_payload(&mut payload);
self.buffer.append_bytes(payload.payload_slice());
}

pub fn remove(&mut self, index: usize) {
Expand Down Expand Up @@ -259,9 +262,9 @@ where
}

pub fn overwrite_with_single_item(&mut self, item: T) {
item.into_byte_writer(|bytes| {
self.buffer.overwrite(bytes);
});
let mut payload = T::PAYLOAD::new_buffer();
item.save_to_payload(&mut payload);
self.buffer.overwrite(payload.payload_slice());
}

/// Appends all the contents of another managed vec at the end of the current one.
Expand Down Expand Up @@ -541,12 +544,16 @@ where
}
let mut byte_index = 0;
while byte_index < self_len {
let self_item = T::from_byte_reader(|dest_slice| {
let _ = self.buffer.load_slice(byte_index, dest_slice);
});
let other_item = T::from_byte_reader(|dest_slice| {
let _ = other.buffer.load_slice(byte_index, dest_slice);
});
let mut self_payload = T::PAYLOAD::new_buffer();
let _ = self
.buffer
.load_slice(byte_index, self_payload.payload_slice_mut());
let mut other_payload = T::PAYLOAD::new_buffer();
let _ = other
.buffer
.load_slice(byte_index, other_payload.payload_slice_mut());
let self_item = T::read_from_payload(&self_payload);
let other_item = T::read_from_payload(&other_payload);
if self_item != other_item {
return false;
}
Expand Down
Loading

0 comments on commit ff19ae5

Please sign in to comment.