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
use std::env;
use std::panic;

use quote::quote;
use syn;
use syn::export::TokenStream;

#[proc_macro_attribute]
pub fn mammoth_module(attr: TokenStream, item: TokenStream) -> TokenStream {
    let constructor: syn::Ident = syn::parse(attr).unwrap();
    let ast: syn::ItemStruct = syn::parse(item).unwrap();
    let name = &ast.ident;

    if env::var("MAMMOTH_MODULE").is_ok() {
        panic!("Only one MammothInterface per library is allowed.");
    } else {
        env::set_var("MAMMOTH_MODULE", "impl");
    }

    let result = quote!{
        trait __mammoth_interface: mammoth_setup::MammothInterface {}

        #[no_mangle]
        pub extern fn __version() -> semver::Version {
            mammoth_setup::version::version()
        }

        #[no_mangle]
        pub extern fn __construct(cfg: Option<toml::Value>) -> *mut mammoth_setup::MammothInterface {
            let interface = Box::new(#constructor(cfg));
            Box::into_raw(interface)
        }

        #ast

        impl __mammoth_interface for #name {}
    };

    result.into()
}