1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#![recursion_limit = "256"]
#![feature(proc_macro_hygiene)]

extern crate proc_macro;
use heck::MixedCase;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Lit};

mod base58;
mod contract;
mod event;

#[proc_macro_attribute]
pub fn contract(_metadata: TokenStream, input: TokenStream) -> TokenStream {
    let item: syn::Item = syn::parse(input).unwrap();
    let stream = contract::quote(item);

    stream.into()
}

#[proc_macro_attribute]
pub fn event(metadata: TokenStream, input: TokenStream) -> TokenStream {
    match syn::parse::<syn::Item>(input).unwrap() {
        syn::Item::Fn(ref func) => {
            use quote::ToTokens;
            let mut method_name;
            if metadata.is_empty() {
                method_name = func.sig.ident.clone().into_token_stream().to_string();
            } else {
                method_name = metadata.to_string();
                method_name = method_name.replace("name", "");
                method_name = method_name.replace("=", "");
            }
            method_name = method_name.to_mixed_case();
            let stream = event::quote(method_name, func);
            stream.into()
        }
        _ => panic!("Only fn is allowed"),
    }
}

#[proc_macro]
pub fn base58(item: TokenStream) -> TokenStream {
    let input = parse_macro_input!(item as Lit);
    let addr = match input {
        syn::Lit::Str(lit_str) => base58::decode_base58(&lit_str.value())
            .unwrap_or_else(|e| panic!("failed to parse base58 address: {}", e)),
        syn::Lit::ByteStr(lit_str) => {
            base58::decode_base58(&String::from_utf8(lit_str.value()).unwrap())
                .unwrap_or_else(|e| panic!("failed to parse base58 address: {}", e))
        }
        _ => panic!("base58! only support string literal"),
    };
    let result = quote! { Address::new([#(#addr),*])};

    result.into()
}