Skip to content

Commit

Permalink
[fix] #4082: Remove cloning for ISI execution in wasm
Browse files Browse the repository at this point in the history
Signed-off-by: Marin Veršić <[email protected]>
  • Loading branch information
mversic committed Feb 19, 2024
1 parent fbdd591 commit e53f58d
Show file tree
Hide file tree
Showing 12 changed files with 569 additions and 157 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl Executor {
})?;

if let Ok(can_unregister_domain_token) =
iroha_executor::default::tokens::domain::CanUnregisterDomain::try_from(token)
iroha_executor::default::tokens::domain::CanUnregisterDomain::try_from(&token)
{
found_accounts.push((account, can_unregister_domain_token.domain_id));
break;
Expand Down
Binary file modified configs/swarm/executor.wasm
Binary file not shown.
177 changes: 177 additions & 0 deletions data_model/derive/src/enum_ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
use darling::{FromAttributes, FromDeriveInput, FromMeta, FromVariant};
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};

pub fn impl_enum_ref(input: &syn2::DeriveInput) -> manyhow::Result<TokenStream> {
let input = EnumRef::from_derive_input(input)?;
Ok(quote! { #input })
}

#[derive(Clone, Copy)]
enum Transparent {
Transparent,
NotTransparent,
}

#[derive(Clone)]
enum EnumRefDeriveAttrs {
Derive(Vec<darling::ast::NestedMeta>),
}

#[derive(Clone, FromAttributes)]
#[darling(attributes(enum_ref))]
struct EnumRefAttrs {
derive: EnumRefDeriveAttrs,
}

#[derive(Clone, Copy, FromAttributes)]
#[darling(attributes(enum_ref))]
struct EnumRefVariantAttrs {
transparent: Transparent,
}

#[derive(Clone)]
struct EnumRefField {
ty: syn2::Type,
}

#[derive(Clone)]
struct EnumRefVariant {
ident: syn2::Ident,
field: EnumRefField,
}

#[derive(Clone)]
struct EnumRef {
attrs: EnumRefAttrs,
ident: syn2::Ident,
generics: syn2::Generics,
data: darling::ast::Data<EnumRefVariant, darling::util::Ignored>,
}

impl FromMeta for Transparent {
fn from_none() -> Option<Self> {
Some(Self::NotTransparent)
}

fn from_word() -> darling::Result<Self> {
Ok(Self::Transparent)
}
}

impl FromMeta for EnumRefDeriveAttrs {
fn from_list(items: &[darling::ast::NestedMeta]) -> darling::Result<Self> {
Ok(Self::Derive(items.to_vec()))
}
}

impl FromVariant for EnumRefVariant {
fn from_variant(variant: &syn2::Variant) -> darling::Result<Self> {
let transparent = EnumRefVariantAttrs::from_attributes(&variant.attrs)?;

let mut fields: Vec<_> = variant
.fields
.iter()
.map(|field| {
assert_eq!(field.ident, None);

EnumRefField {
ty: gen_field_ty(transparent.transparent, &field.ty),
}
})
.collect();

if fields.len() > 1 {
return Err(darling::Error::custom(
"Enums with more than 1 unnamed field are not supported",
)
.with_span(&variant.fields));
}

Ok(Self {
ident: variant.ident.clone(),
field: fields.swap_remove(0),
})
}
}

impl FromDeriveInput for EnumRef {
fn from_derive_input(input: &syn2::DeriveInput) -> darling::Result<Self> {
Ok(Self {
attrs: EnumRefAttrs::from_attributes(&input.attrs)?,
ident: gen_enum_ref_ident(&input.ident),
generics: input.generics.clone(),
data: darling::ast::Data::try_from(&input.data)?,
})
}
}

impl ToTokens for EnumRefAttrs {
fn to_tokens(&self, tokens: &mut TokenStream) {
let EnumRefDeriveAttrs::Derive(derive) = &self.derive;
quote! {
#[derive(#(#derive),*)]
}
.to_tokens(tokens);
}
}

impl ToTokens for EnumRefField {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.ty.to_tokens(tokens);
}
}

impl ToTokens for EnumRefVariant {
fn to_tokens(&self, tokens: &mut TokenStream) {
let EnumRefVariant { ident, field } = self;

quote! {
#ident(#field)
}
.to_tokens(tokens);
}
}

impl ToTokens for EnumRef {
fn to_tokens(&self, tokens: &mut TokenStream) {
let EnumRef {
attrs,
ident,
generics,
data,
} = self;

let (impl_generics, _, where_clause) = generics.split_for_impl();
let variants = if let darling::ast::Data::Enum(variants) = data {
variants
} else {
unreachable!()
};

quote! {
#attrs
pub(super) enum #ident<'a> #impl_generics #where_clause {
#(#variants),*
}
}
.to_tokens(tokens);
}
}

fn gen_enum_ref_ident(ident: &syn2::Ident) -> syn2::Ident {
syn2::Ident::new(&format!("{ident}Ref"), proc_macro2::Span::call_site())
}

fn gen_field_ty(transparent: Transparent, field_ty: &syn2::Type) -> syn2::Type {
if matches!(transparent, Transparent::Transparent) {
if let syn2::Type::Path(ty) = field_ty {
if let Some(ident) = ty.path.get_ident() {
let ident = gen_enum_ref_ident(ident);
return syn2::parse_quote! { #ident<'a> };
}
}
}

syn2::parse_quote!(&'a #field_ty)
}
44 changes: 44 additions & 0 deletions data_model/derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! A crate containing various derive macros for `data_model`
mod enum_ref;
mod filter;
mod has_origin;
mod id;
Expand All @@ -9,6 +10,49 @@ use iroha_macro_utils::Emitter;
use manyhow::{emit, manyhow, Result};
use proc_macro2::TokenStream;

/// Construct a matching enum with references in place of enum variant fields
///
/// # Example
///
/// ```rust
/// use iroha_data_model_derive::EnumRef;
/// use parity_scale_codec::Encode;
///
/// #[derive(EnumRef)]
/// enum InnerEnum {
/// A(u32),
/// B(i32)
/// }
///
/// #[derive(EnumRef)]
/// #[enum_ref(derive(Encode))]
/// enum OuterEnum {
/// A(String),
/// #[enum_ref(transparent)]
/// B(InnerEnum),
/// }
///
/// /* will produce:
///
/// enum InnerEnumRef<'a> {
/// A(&'a u32),
/// B(&'a i32),
/// }
///
/// enum OuterEnumRef<'a> {
/// A(&'a String),
/// B(InnerEnumRef<'a>),
/// }
/// */
/// ```
///
#[manyhow]
#[proc_macro_derive(EnumRef, attributes(enum_ref))]
pub fn enum_ref(input: TokenStream) -> Result<TokenStream> {
let input = syn2::parse2(input)?;
enum_ref::impl_enum_ref(&input)
}

/// Macro which controls how to export item's API. The behaviour is controlled with `transparent_api`
/// feature flag. If the flag is active, item's public fields will be exposed as public, however, if
/// it's not active, item will be exposed as opaque, i.e. no fields will be visible. This enables
Expand Down
Loading

0 comments on commit e53f58d

Please sign in to comment.