Skip to content

Commit

Permalink
Merge pull request #1854 from multiversx/man-opt-refactor
Browse files Browse the repository at this point in the history
ManagedOption refactor + forget_into_handle
  • Loading branch information
andrei-marinica authored Nov 22, 2024
2 parents de44b3e + 835d656 commit 43d5c1f
Show file tree
Hide file tree
Showing 17 changed files with 116 additions and 32 deletions.
4 changes: 4 additions & 0 deletions framework/base/src/storage/storage_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ where
self.buffer.get_handle()
}

unsafe fn forget_into_handle(self) -> Self::OwnHandle {
self.buffer.forget_into_handle()
}

fn transmute_from_handle_ref(handle_ref: &A::ManagedBufferHandle) -> &Self {
unsafe { core::mem::transmute(handle_ref) }
}
Expand Down
4 changes: 4 additions & 0 deletions framework/base/src/types/interaction/managed_arg_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ where
self.data.get_handle()
}

unsafe fn forget_into_handle(self) -> Self::OwnHandle {
self.data.forget_into_handle()
}

fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self {
unsafe { core::mem::transmute(handle_ref) }
}
Expand Down
8 changes: 8 additions & 0 deletions framework/base/src/types/managed/basic/big_float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ impl<M: ManagedTypeApi> ManagedType<M> for BigFloat<M> {
self.handle.clone()
}

unsafe fn forget_into_handle(self) -> Self::OwnHandle {
unsafe {
let handle = core::ptr::read(&self.handle);
core::mem::forget(self);
handle
}
}

fn transmute_from_handle_ref(handle_ref: &M::BigFloatHandle) -> &Self {
unsafe { core::mem::transmute(handle_ref) }
}
Expand Down
8 changes: 8 additions & 0 deletions framework/base/src/types/managed/basic/big_int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ impl<M: ManagedTypeApi> ManagedType<M> for BigInt<M> {
self.handle.clone()
}

unsafe fn forget_into_handle(self) -> Self::OwnHandle {
unsafe {
let handle = core::ptr::read(&self.handle);
core::mem::forget(self);
handle
}
}

fn transmute_from_handle_ref(handle_ref: &M::BigIntHandle) -> &Self {
unsafe { core::mem::transmute(handle_ref) }
}
Expand Down
8 changes: 8 additions & 0 deletions framework/base/src/types/managed/basic/elliptic_curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ impl<M: ManagedTypeApi> ManagedType<M> for EllipticCurve<M> {
self.handle.clone()
}

unsafe fn forget_into_handle(self) -> Self::OwnHandle {
unsafe {
let handle = core::ptr::read(&self.handle);
core::mem::forget(self);
handle
}
}

fn transmute_from_handle_ref(handle_ref: &M::EllipticCurveHandle) -> &Self {
unsafe { core::mem::transmute(handle_ref) }
}
Expand Down
8 changes: 8 additions & 0 deletions framework/base/src/types/managed/basic/managed_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ impl<M: ManagedTypeApi> ManagedType<M> for ManagedBuffer<M> {
self.handle.clone()
}

unsafe fn forget_into_handle(self) -> Self::OwnHandle {
unsafe {
let handle = core::ptr::read(&self.handle);
core::mem::forget(self);
handle
}
}

fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self {
unsafe { core::mem::transmute(handle_ref) }
}
Expand Down
8 changes: 8 additions & 0 deletions framework/base/src/types/managed/basic/managed_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ impl<M: ManagedTypeApi> ManagedType<M> for ManagedMap<M> {
self.handle.clone()
}

unsafe fn forget_into_handle(self) -> Self::OwnHandle {
unsafe {
let handle = core::ptr::read(&self.handle);
core::mem::forget(self);
handle
}
}

fn transmute_from_handle_ref(handle_ref: &M::ManagedMapHandle) -> &Self {
unsafe { core::mem::transmute(handle_ref) }
}
Expand Down
15 changes: 15 additions & 0 deletions framework/base/src/types/managed/managed_type_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@ pub trait ManagedType<M: ManagedTypeApi>: Sized {

fn get_handle(&self) -> Self::OwnHandle;

/// Forgets current object (does not run destructor), but extracts the handle.
///
/// The handle remains an owned object, so the handle's destructor will run later, when dropped.
///
/// ## Safety
///
/// Destructures the object, without running a constructor.
///
/// To avoid a memory leak, it is necessary for the object to be later
/// reconstructed from handle and its destructor run.
///
/// It is designed to be used ManagedVec and ManagedOption,
/// where items are dropped later, together with their container.
unsafe fn forget_into_handle(self) -> Self::OwnHandle;

#[doc(hidden)]
unsafe fn from_raw_handle(handle: RawHandle) -> Self {
Self::from_handle(Self::OwnHandle::new(handle))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ where
self.0.get_handle()
}

unsafe fn forget_into_handle(self) -> Self::OwnHandle {
self.0.forget_into_handle()
}

fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self {
unsafe { core::mem::transmute(handle_ref) }
}
Expand Down
4 changes: 4 additions & 0 deletions framework/base/src/types/managed/wrapped/big_uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ impl<M: ManagedTypeApi> ManagedType<M> for BigUint<M> {
self.value.handle.clone()
}

unsafe fn forget_into_handle(self) -> Self::OwnHandle {
self.value.forget_into_handle()
}

fn transmute_from_handle_ref(handle_ref: &M::BigIntHandle) -> &Self {
unsafe { core::mem::transmute(handle_ref) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ use crate as multiversx_sc; // required by the ManagedVecItem derive
///
/// It is, however more optimized than that. Its implementation is based on `ManagedOption`.
///
/// EGLD a special, invalid token identifier handle. This way we can fit it inside a single i32 in memory.
/// EGLD is indicated by a special, invalid token identifier handle.
/// This way we can fit it inside a single i32 in memory.
#[repr(transparent)]
#[derive(ManagedVecItem, Clone)]
pub struct EgldOrEsdtTokenIdentifier<M: ManagedTypeApi> {
Expand Down Expand Up @@ -56,13 +57,6 @@ impl<M: ManagedTypeApi> EgldOrEsdtTokenIdentifier<M> {
}
}

pub fn from_opt_raw_handle(opt_handle: Option<M::ManagedBufferHandle>) -> Self {
match opt_handle {
Some(handle) => Self::esdt(unsafe { TokenIdentifier::from_handle(handle) }),
None => Self::egld(),
}
}

pub fn parse(data: ManagedBuffer<M>) -> Self {
if data == Self::EGLD_REPRESENTATION {
Self::egld()
Expand Down Expand Up @@ -268,13 +262,15 @@ where
M: ManagedTypeApi,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if let Some(token_identifier) = self.data.as_option() {
let token_id_str = token_identifier.to_string();
f.debug_tuple("EgldOrEsdtTokenIdentifier::Esdt")
.field(&token_id_str)
.finish()
} else {
f.write_str("EgldOrEsdtTokenIdentifier::Egld")
}
self.map_ref_or_else(
f,
|f| f.write_str("EgldOrEsdtTokenIdentifier::Egld"),
|f, token_identifier| {
let token_id_str = token_identifier.to_string();
f.debug_tuple("EgldOrEsdtTokenIdentifier::Esdt")
.field(&token_id_str)
.finish()
},
)
}
}
4 changes: 4 additions & 0 deletions framework/base/src/types/managed/wrapped/managed_address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ where
self.bytes.get_handle()
}

unsafe fn forget_into_handle(self) -> Self::OwnHandle {
self.bytes.forget_into_handle()
}

fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self {
unsafe { core::mem::transmute(handle_ref) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ where
self.buffer.get_handle()
}

unsafe fn forget_into_handle(self) -> Self::OwnHandle {
self.buffer.forget_into_handle()
}

fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self {
unsafe { core::mem::transmute(handle_ref) }
}
Expand Down
27 changes: 13 additions & 14 deletions framework/base/src/types/managed/wrapped/managed_option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ where
}

pub fn some(value: T) -> Self {
Self::new_with_handle(value.get_handle())
unsafe { Self::new_with_handle(value.forget_into_handle()) }
}

pub fn none() -> Self {
Expand Down Expand Up @@ -143,7 +143,12 @@ where
F: FnOnce(Context, &T) -> R,
{
if self.is_some() {
f(context, unsafe { &T::from_handle(self.handle.clone()) })
unsafe {
let obj = T::from_handle(self.handle.clone());
let result = f(context, &obj);
let _ = obj.forget_into_handle();
result
}
} else {
default(context)
}
Expand All @@ -157,11 +162,7 @@ where
{
#[allow(clippy::redundant_clone)] // the clone is not redundant
fn clone(&self) -> Self {
if self.is_some() {
Self::some(unsafe { T::from_handle(self.handle.clone()) }.clone())
} else {
Self::none()
}
self.map_ref_or_else((), |()| Self::none(), |(), obj| Self::some(obj.clone()))
}
}

Expand Down Expand Up @@ -328,12 +329,10 @@ where
T: ManagedType<M> + core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if self.is_some() {
f.debug_tuple("ManagedOption::Some")
.field(unsafe { &T::from_handle(self.handle.clone()) })
.finish()
} else {
f.write_str("ManagedOption::None")
}
self.map_ref_or_else(
f,
|f| f.write_str("ManagedOption::None"),
|f, obj| f.debug_tuple("ManagedOption::Some").field(obj).finish(),
)
}
}
4 changes: 4 additions & 0 deletions framework/base/src/types/managed/wrapped/managed_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ where
self.buffer.get_handle()
}

unsafe fn forget_into_handle(self) -> Self::OwnHandle {
self.buffer.forget_into_handle()
}

fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self {
unsafe { core::mem::transmute(handle_ref) }
}
Expand Down
6 changes: 4 additions & 2 deletions framework/base/src/types/managed/wrapped/managed_vec_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ macro_rules! impl_managed_type {
}

fn into_byte_writer<R, Writer: FnMut(&[u8]) -> R>(self, writer: Writer) -> R {
<$ty<M> as ManagedType<M>>::OwnHandle::into_byte_writer(self.get_handle(), writer)
let handle = unsafe { self.forget_into_handle() };
<$ty<M> as ManagedType<M>>::OwnHandle::into_byte_writer(handle, writer)
}
}
};
Expand Down Expand Up @@ -266,7 +267,8 @@ where
}

fn into_byte_writer<R, Writer: FnMut(&[u8]) -> R>(self, writer: Writer) -> R {
<M::ManagedBufferHandle as ManagedVecItem>::into_byte_writer(self.get_handle(), writer)
let handle = unsafe { self.forget_into_handle() };
<M::ManagedBufferHandle as ManagedVecItem>::into_byte_writer(handle, writer)
}
}

Expand Down
4 changes: 4 additions & 0 deletions framework/base/src/types/managed/wrapped/token_identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ impl<M: ManagedTypeApi> ManagedType<M> for TokenIdentifier<M> {
self.buffer.get_handle()
}

unsafe fn forget_into_handle(self) -> Self::OwnHandle {
self.buffer.forget_into_handle()
}

fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self {
unsafe { core::mem::transmute(handle_ref) }
}
Expand Down

0 comments on commit 43d5c1f

Please sign in to comment.