Skip to content
This repository has been archived by the owner on Oct 25, 2024. It is now read-only.

Commit

Permalink
move predicate to macros
Browse files Browse the repository at this point in the history
  • Loading branch information
ra0x3 committed Oct 5, 2023
1 parent 6d1a5e8 commit 2442d6e
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 96 deletions.
26 changes: 20 additions & 6 deletions packages/fuel-indexer-lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,36 @@ pub enum ExecutionSource {
Wasm,
}

/// A small wrapper for a set of tokens based on the execution method used.
///
/// Native execution requires tokens like `async` and `await`, whereas WASM
/// execution does not.
pub struct ExecutionSourceTokens {

/// `async` token
pub asyncness: TokenStream,

/// `.await` token
pub awaitness: TokenStream,

/// Trait used when implementing some `From`-like operations.
///
/// WASM execution uses the standard `From` trait whereas native execution
/// uses a custom `AsyncFrom` trait.
pub trait_name: TokenStream,


/// Function name used when implementing some `From`-like operations.
pub trait_fn_name: TokenStream,

/// Attribute used when implementing some `From`-like operations. `AsyncFrom`
/// requires a `#[async_trait]` attribute.
pub trait_attribute: TokenStream,
}

impl ExecutionSource {
pub fn async_awaitness(&self) -> (TokenStream, TokenStream) {
match self {
Self::Native => (quote! {async}, quote! {.await}),
Self::Wasm => (quote! {}, quote! {}),
}
}

/// Return a set of tokens based on the execution method used.
pub fn tokens_bundle(&self) -> ExecutionSourceTokens {
match self {
ExecutionSource::Native => ExecutionSourceTokens {
Expand Down
90 changes: 2 additions & 88 deletions packages/fuel-indexer-macros/src/decoder.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::helpers::*;
use crate::{helpers::*, predicate_tokens};
use async_graphql_parser::types::{
FieldDefinition, ObjectType, TypeDefinition, TypeKind,
};
Expand Down Expand Up @@ -234,91 +234,9 @@ impl From<ImplementationDecoder> for TokenStream {
let ExecutionSourceTokens {
asyncness,
awaitness,
trait_name,
trait_fn_name,
trait_attribute,
..
} = exec_source.tokens_bundle();

let impl_predicate_witness_data = match typ_name.as_str() {
"PredicateWitnessDataEntity" => {
quote! {
#trait_attribute
impl #trait_name <PredicateWitnessData> for PredicateWitnessDataEntity {
#asyncness fn #trait_fn_name(data: PredicateWitnessData) -> Self {

let commitment = data.template_commitment();
let configuration = data.configuration_schema();
let output_index = data.output_index();
let input_index = data.input_index();

Self::new(commitment.to_owned(), configuration.to_owned(), output_index.to_owned(), input_index.to_owned()).get_or_create()#awaitness
}
}

#trait_attribute
impl #trait_name <PredicateWitnessDataEntity> for PredicateWitnessData {
#asyncness fn #trait_fn_name(entity: PredicateWitnessDataEntity) -> Self {
let PredicateWitnessDataEntity {
id,
template_commitment,
configuration_schema,
output_index,
input_index,
} = entity;

Self::new_from_entity(id.to_owned(), template_commitment.to_owned(), configuration_schema.to_owned(), output_index.to_owned(), input_index.to_owned())
}
}
}
}
_ => quote! {},
};

let impl_predicate = match typ_name.as_str() {
"PredicateEntity" => {
quote! {

#trait_attribute
impl #trait_name <Predicate> for PredicateEntity {
#asyncness fn #trait_fn_name(predicate: Predicate) -> Self {
let coin_input = predicate.coin_input();
let coin_output = predicate.coin_output();
let witness_data = predicate.witness_data();
let create_tx_hash = predicate.create_tx_hash();
let spend_tx_hash = predicate.spend_tx_hash();

let witness_data = PredicateWitnessDataEntity::#trait_fn_name(witness_data.to_owned())#awaitness;

let coin_input = bincode::serialize(&coin_input).expect("Could not serialize coin input.");
let coin_output = bincode::serialize(&coin_output).expect("Could not serialize coin output.");

Self::new(witness_data.id, create_tx_hash.to_owned(), spend_tx_hash.to_owned(), coin_input.into(), coin_output.into()).get_or_create()#awaitness
}
}

#trait_attribute
impl #trait_name<PredicateEntity> for Predicate {
#asyncness fn #trait_fn_name(entity: PredicateEntity) -> Self {
let PredicateEntity {
id,
witness_data,
spend_tx_hash,
create_tx_hash,
coin_input,
coin_output,
} = entity;

let witness_data = PredicateWitnessDataEntity::load(witness_data)#awaitness.expect("Could not load witness data.");
let witness_data = PredicateWitnessData::#trait_fn_name(witness_data)#awaitness;

Self::new_from_entity(id, witness_data, spend_tx_hash, create_tx_hash, coin_input, coin_output)
}
}
}
}
_ => quote! {},
};

let impl_get_or_create = quote! {
pub #asyncness fn get_or_create(self) -> Self {
match Self::load(self.id.clone())#awaitness {
Expand Down Expand Up @@ -360,10 +278,6 @@ impl From<ImplementationDecoder> for TokenStream {

#impl_get_or_create
}

#impl_predicate_witness_data

#impl_predicate
}
}
TypeKind::Union(u) => {
Expand Down
15 changes: 13 additions & 2 deletions packages/fuel-indexer-macros/src/indexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use crate::{
parse::IndexerConfig,
schema::process_graphql_schema,
wasm::handler_block_wasm,
predicate_tokens,
};
use fuel_abi_types::abi::program::TypeDeclaration;
use fuel_indexer_lib::{
constants::*, manifest::Manifest, utils::workspace_manifest_prefix, ExecutionSource,
constants::*, manifest::Manifest, utils::workspace_manifest_prefix, ExecutionSource, ExecutionSourceTokens,
};
use fuel_indexer_types::{type_id, FUEL_TYPES_NAMESPACE};
use fuels::{core::codec::resolve_fn_selector, types::param_types::ParamType};
Expand Down Expand Up @@ -447,7 +448,11 @@ fn process_fn_items(
None => quote! {},
};

let (asyncness, awaitness) = manifest.execution_source().async_awaitness();
let ExecutionSourceTokens {
asyncness,
awaitness,
..
} = manifest.execution_source().tokens_bundle();

for item in contents {
match item {
Expand Down Expand Up @@ -973,6 +978,8 @@ pub fn process_indexer_module(attrs: TokenStream, item: TokenStream) -> TokenStr

let decl_tokens = additional_declarations();

let predicate_tokens = predicate_tokens(&manifest.execution_source());

let output = match manifest.execution_source() {
ExecutionSource::Native => {
let (handler_block, fn_items) =
Expand All @@ -990,6 +997,8 @@ pub fn process_indexer_module(attrs: TokenStream, item: TokenStream) -> TokenStr

#graphql_tokens

#predicate_tokens

#handler_block

#fn_items
Expand All @@ -1011,6 +1020,8 @@ pub fn process_indexer_module(attrs: TokenStream, item: TokenStream) -> TokenStr

#graphql_tokens

#predicate_tokens

#handler_block

#fn_items
Expand Down
82 changes: 82 additions & 0 deletions packages/fuel-indexer-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ pub(crate) mod schema;
pub(crate) mod wasm;

use indexer::process_indexer_module;
use fuel_indexer_lib::{ExecutionSource, ExecutionSourceTokens};
use predicate::process_predicate_module;
use proc_macro::TokenStream;
use quote::quote;

#[proc_macro_error::proc_macro_error]
#[proc_macro_attribute]
Expand All @@ -25,3 +27,83 @@ pub fn indexer(attrs: TokenStream, item: TokenStream) -> TokenStream {
pub fn predicate(attrs: TokenStream, item: TokenStream) -> TokenStream {
process_predicate_module(attrs, item)
}


/// Generate a set of tokens for converting predicate types between their ABI-like type
/// (e.g., `Predicate`) and their Entity-like type (e.g., `PredicateEntity`).
pub(crate) fn predicate_tokens(exec_source: &ExecutionSource) -> proc_macro2::TokenStream {
let ExecutionSourceTokens {
asyncness,
awaitness,
trait_name,
trait_fn_name,
trait_attribute,
} = exec_source.tokens_bundle();

quote! {
#trait_attribute
impl #trait_name <PredicateWitnessData> for PredicateWitnessDataEntity {
#asyncness fn #trait_fn_name(data: PredicateWitnessData) -> Self {

let commitment = data.template_commitment();
let configuration = data.configuration_schema();
let output_index = data.output_index();
let input_index = data.input_index();

Self::new(commitment.to_owned(), configuration.to_owned(), output_index.to_owned(), input_index.to_owned()).get_or_create()#awaitness
}
}

#trait_attribute
impl #trait_name <PredicateWitnessDataEntity> for PredicateWitnessData {
#asyncness fn #trait_fn_name(entity: PredicateWitnessDataEntity) -> Self {
let PredicateWitnessDataEntity {
id,
template_commitment,
configuration_schema,
output_index,
input_index,
} = entity;

Self::new_from_entity(id.to_owned(), template_commitment.to_owned(), configuration_schema.to_owned(), output_index.to_owned(), input_index.to_owned())
}
}

#trait_attribute
impl #trait_name <Predicate> for PredicateEntity {
#asyncness fn #trait_fn_name(predicate: Predicate) -> Self {
let coin_input = predicate.coin_input();
let coin_output = predicate.coin_output();
let witness_data = predicate.witness_data();
let create_tx_hash = predicate.create_tx_hash();
let spend_tx_hash = predicate.spend_tx_hash();

let witness_data = PredicateWitnessDataEntity::#trait_fn_name(witness_data.to_owned())#awaitness;

let coin_input = bincode::serialize(&coin_input).expect("Could not serialize coin input.");
let coin_output = bincode::serialize(&coin_output).expect("Could not serialize coin output.");

Self::new(witness_data.id, create_tx_hash.to_owned(), spend_tx_hash.to_owned(), coin_input.into(), coin_output.into()).get_or_create()#awaitness
}
}

#trait_attribute
impl #trait_name<PredicateEntity> for Predicate {
#asyncness fn #trait_fn_name(entity: PredicateEntity) -> Self {
let PredicateEntity {
id,
witness_data,
spend_tx_hash,
create_tx_hash,
coin_input,
coin_output,
} = entity;

let witness_data = PredicateWitnessDataEntity::load(witness_data)#awaitness.expect("Could not load witness data.");
let witness_data = PredicateWitnessData::#trait_fn_name(witness_data)#awaitness;

Self::new_from_entity(id, witness_data, spend_tx_hash, create_tx_hash, coin_input, coin_output)
}
}
}
}

0 comments on commit 2442d6e

Please sign in to comment.