Skip to content

Commit

Permalink
rust: Stylized name builder
Browse files Browse the repository at this point in the history
  • Loading branch information
jakelang committed May 6, 2019
1 parent 4747286 commit 626a322
Showing 1 changed file with 50 additions and 3 deletions.
53 changes: 50 additions & 3 deletions bindings/rust/evmc-bind/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ extern crate proc_macro;

use heck::ShoutySnakeCase;
use heck::SnakeCase;
use heck::TitleCase;
use proc_macro::TokenStream;
use syn::parse_macro_input;
use syn::ItemStruct;
use syn::Lit;
use syn::Meta;
use syn::MetaList;
use syn::NestedMeta;

#[proc_macro_attribute]
pub fn evmc_raw(_attr: TokenStream, item: TokenStream) -> TokenStream {
pub fn evmc_raw(args: TokenStream, item: TokenStream) -> TokenStream {
// First, try to parse the input token stream into an AST node representing a struct
// declaration.
let input: ItemStruct = parse_macro_input!(item as ItemStruct);
Expand All @@ -17,9 +22,51 @@ pub fn evmc_raw(_attr: TokenStream, item: TokenStream) -> TokenStream {

// Get the name in shouty snake case for the statically defined VM data.
let vm_name_allcaps: String = vm_type_name.to_shouty_snake_case();

// Get the name in snake case and strip the underscores for the symbol name.
let vm_name_lowercase: String = vm_type_name.to_snake_case().chars().filter(|c| *c != '_').collect();
let vm_name_lowercase: String = vm_type_name
.to_snake_case()
.chars()
.filter(|c| *c != '_')
.collect();

// The stylized VM name can optionally be included as an argument for the attribute. If it is
// not provided, the stylized name defaults to the name of the VM struct in title case.
let vm_name_stylized: String = if !args.is_empty() {
let meta = parse_macro_input!(args as MetaList);

// If we have more than one argument, throw a compile error. Otherwise, extract the item
// and try to form a valid stylized name from it.
if meta.nested.len() != 1 {
panic!("More than one meta-item supplied to evmc_raw")
} else {
match meta
.nested
.first()
.expect("Meta-item list missing a first element.")
.into_value()
{
NestedMeta::Meta(m) => {
// Try to form a string from the identifier if a meta-item was supplied.
if let Meta::Word(id) = m {
id.to_string()
} else {
panic!("Meta-item passed to evmc_raw is not a valid identifier")
}
}
NestedMeta::Literal(l) => {
// Try to extract a valid UTF-8 string if a literal was supplied.
if let Lit::Str(s) = l {
s.value()
} else {
panic!("Literal passed to evmc_raw is not a valid UTF-8 string literal")
}
}
}
}
} else {
vm_type_name.to_title_case()
};

// struct declaration transformation
// capabilities
Expand Down

0 comments on commit 626a322

Please sign in to comment.