Skip to content

Commit

Permalink
enable the 'skip_empty_output' instruction in all maps and stores by …
Browse files Browse the repository at this point in the history
…default
  • Loading branch information
sduchesneau committed Sep 27, 2024
1 parent 0db544f commit a68ee3a
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 11 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

- Enable the 'skip_empty_output' instruction in all maps and stores by default, unless the macro is called with the keep_empty_output parameter, like this:
`#[substreams::handlers::map(keep_empty_output)]`

## 0.5.22

- Added [ExprMatcher](https://docs.rs/substreams/latest/substreams/struct.ExprMatcher.html), and constructor(s) [expr_matcher](https://docs.rs/substreams/latest/substreams/struct.ExprMatcher.html#method.new) and [ExprMatcher::new](https://docs.rs/substreams/latest/substreams/fn.expr_matcher.html). This can be used to parse an expression once and re-used it to run multiple [matches_keys](https://docs.rs/substreams/latest/substreams/struct.ExprMatcher.html#method.matches_keys) against different keys:
Expand Down
22 changes: 21 additions & 1 deletion substreams-macro/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote, ToTokens};
use syn::spanned::Spanned;

pub fn main(item: TokenStream, module_type: ModuleType) -> TokenStream {
pub fn main(item: TokenStream, module_type: ModuleType, keep_empty_output: bool) -> TokenStream {

let original = item.clone();

let final_config = FinalConfiguration { module_type };
Expand Down Expand Up @@ -125,6 +126,7 @@ pub fn main(item: TokenStream, module_type: ModuleType) -> TokenStream {
proto_decodings,
read_only_stores,
writable_store,
keep_empty_output,
),
ModuleType::Map => {
if output_type == OutputType::Void {
Expand All @@ -144,6 +146,7 @@ pub fn main(item: TokenStream, module_type: ModuleType) -> TokenStream {
proto_decodings,
read_only_stores,
writable_store,
keep_empty_output,
)
}
}
Expand Down Expand Up @@ -301,6 +304,7 @@ fn build_map_handler(
decodings: Vec<proc_macro2::TokenStream>,
read_only_stores: Vec<proc_macro2::TokenStream>,
writable_store: proc_macro2::TokenStream,
keep_empty_output: bool,
) -> TokenStream {
let body = &input.block;
let header = quote! {
Expand Down Expand Up @@ -356,11 +360,19 @@ fn build_map_handler(
}
};

let skip_empty_output = match keep_empty_output {
true => quote! {},
false => quote! {
substreams::skip_empty_output();
},
};

let result = quote! {
#header
pub extern "C" fn #func_name(#(#collected_args),*){
substreams::register_panic_hook();
#lambda
#skip_empty_output
let result = func();
#output_handler
}
Expand All @@ -374,19 +386,27 @@ fn build_store_handler(
decodings: Vec<proc_macro2::TokenStream>,
read_only_stores: Vec<proc_macro2::TokenStream>,
writable_store: proc_macro2::TokenStream,
keep_empty_output: bool,
) -> TokenStream {
let body = &input.block;
let header = quote! {
#[no_mangle]
};
let func_name = input.sig.ident.clone();
let skip_empty_output = match keep_empty_output {
true => quote! {},
false => quote! {
substreams::skip_empty_output();
},
};
let result = quote! {
#header
pub extern "C" fn #func_name(#(#collected_args),*){
substreams::register_panic_hook();
#(#decodings)*
#(#read_only_stores)*
#writable_store
#skip_empty_output
let result = #body;
result
}
Expand Down
113 changes: 103 additions & 10 deletions substreams-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,25 @@ mod handler;
mod store;

#[proc_macro_attribute]
pub fn map(_args: TokenStream, item: TokenStream) -> TokenStream {
handler::main(item.into(), config::ModuleType::Map).into()
pub fn map(args: TokenStream, item: TokenStream) -> TokenStream {
let mut keep_empty_output = false;
match args.to_string().as_str() {
"" => {},
"keep_empty_output" => {keep_empty_output = true},
_ => panic!("Invalid argument '{}' for map macro", args)
}
handler::main(item.into(), config::ModuleType::Map, keep_empty_output).into()
}

#[proc_macro_attribute]
pub fn store(_args: TokenStream, item: TokenStream) -> TokenStream {
handler::main(item.into(), config::ModuleType::Store).into()
pub fn store(args: TokenStream, item: TokenStream) -> TokenStream {
let mut keep_empty_output = false;
match args.to_string().as_str() {
"" => {},
"keep_empty_output" => {keep_empty_output = true},
_ => panic!("Invalid argument '{}' for store macro", args)
}
handler::main(item.into(), config::ModuleType::Store, keep_empty_output).into()
}

// todo: remove this once satisfied with implementation of StoreDelete
Expand All @@ -36,7 +48,7 @@ mod test {
};

assert_ast_eq(
main(item, ModuleType::Map).into(),
main(item, ModuleType::Map, true).into(),
quote! {
#[no_mangle]
pub extern "C" fn map_transfers(blk_ptr: *mut u8, blk_len: usize) {
Expand Down Expand Up @@ -65,7 +77,7 @@ mod test {
};

assert_ast_eq(
main(item, ModuleType::Map).into(),
main(item, ModuleType::Map, true).into(),
quote! {
#[no_mangle]
pub extern "C" fn map_transfers(blk_ptr: *mut u8, blk_len: usize) {
Expand Down Expand Up @@ -94,7 +106,7 @@ mod test {
};

assert_ast_eq(
main(item, ModuleType::Map).into(),
main(item, ModuleType::Map, true).into(),
quote! {
#[no_mangle]
pub extern "C" fn map_transfers(blk_ptr: *mut u8, blk_len: usize) {
Expand Down Expand Up @@ -124,7 +136,7 @@ mod test {
};

assert_ast_eq(
main(item, ModuleType::Map).into(),
main(item, ModuleType::Map, true).into(),
quote! {
#[no_mangle]
pub extern "C" fn map_transfers(blk_ptr: *mut u8, blk_len: usize) {
Expand Down Expand Up @@ -155,7 +167,7 @@ mod test {
};

assert_ast_eq(
main(item, ModuleType::Map).into(),
main(item.clone(), ModuleType::Map, true).into(),
quote! {
#[no_mangle]
pub extern "C" fn map_transfers(blk_ptr: *mut u8, blk_len: usize) {
Expand All @@ -177,5 +189,86 @@ mod test {
}
},
);

assert_ast_eq(
main(item, ModuleType::Map, false).into(),
quote! {
#[no_mangle]
pub extern "C" fn map_transfers(blk_ptr: *mut u8, blk_len: usize) {
substreams::register_panic_hook();
let func = || -> Result<Option<pb::Custom> > {
let blk: eth::Block = substreams::proto::decode_ptr(blk_ptr, blk_len)
.unwrap_or_else(|_| panic!("Unable to decode Protobuf data ({} bytes) to '{}' message's struct", blk_len, stringify!(eth::Block)));
let result = { unimplemented!("do something"); };
result
};

substreams :: skip_empty_output () ;
let result = func();
if result.is_err() {
panic!("{:?}", result.unwrap_err())
}
if let Some(inner) = result.expect("already checked that result is not an error") {
substreams::output(inner);
}
}
},
);

}
}

#[test]
fn test_store_result_option() {
let item = quote! {
fn store_values(blk: eth::Block, store: StoreAddInt64) {
unimplemented!("do something");
}
};

assert_ast_eq(
main(item.clone(), ModuleType::Store, true).into(),
quote! {
#[no_mangle]
pub extern "C" fn store_values(blk_ptr: *mut u8, blk_len: usize) {
substreams::register_panic_hook();
let blk: eth::Block = substreams::proto::decode_ptr(blk_ptr, blk_len)
.unwrap_or_else(|_|
panic!(
"Unable to decode Protobuf data ({} bytes) to '{}' message's struct",
blk_len, stringify!(eth::Block)
)
);
let store: StoreAddInt64 = StoreAddInt64::new();
let result = {
unimplemented!("do something");
};
result
}
},
);

assert_ast_eq(
main(item, ModuleType::Store, false).into(),
quote! {
#[no_mangle]
pub extern "C" fn store_values(blk_ptr: *mut u8, blk_len: usize) {
substreams::register_panic_hook();
let blk: eth::Block = substreams::proto::decode_ptr(blk_ptr, blk_len)
.unwrap_or_else(|_|
panic!(
"Unable to decode Protobuf data ({} bytes) to '{}' message's struct",
blk_len, stringify!(eth::Block)
)
);
let store: StoreAddInt64 = StoreAddInt64::new();
substreams :: skip_empty_output () ;
let result = {
unimplemented!("do something");
};
result
}
},
);

}
}

0 comments on commit a68ee3a

Please sign in to comment.