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 f4aa95e
Show file tree
Hide file tree
Showing 12 changed files with 573 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.
175 changes: 175 additions & 0 deletions data_model/derive/src/enum_ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
use darling::{FromAttributes, FromDeriveInput, FromMeta, FromVariant};
use iroha_macro_utils::Emitter;
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};

pub fn impl_enum_ref(_emitter: &mut Emitter, input: &syn2::DeriveInput) -> TokenStream {
let input = EnumRef::from_derive_input(input).unwrap();
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 {
unimplemented!()
}

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)
}
50 changes: 50 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,55 @@ 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) -> TokenStream {
let mut emitter = Emitter::new();

let Some(input) = emitter.handle(syn2::parse2(input)) else {
return emitter.finish_token_stream();
};

let enum_ref = enum_ref::impl_enum_ref(&mut emitter, &input);
emitter.finish_token_stream_with(enum_ref)
}

/// 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 f4aa95e

Please sign in to comment.