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
60
61
62
63
64
use syn::parse_macro_input;
#[cfg(feature = "kinded")]
mod kinded;
#[cfg(feature = "sumtype")]
mod sum_type;

fn handle_syn_result(r: syn::Result<proc_macro2::TokenStream>) -> proc_macro::TokenStream {
    match r {
        Ok(v) => v.into(),
        Err(e) => e.to_compile_error().into(),
    }
}

#[cfg(feature = "kinded")]
#[proc_macro_attribute]
pub fn kinded(
    attrs_ts: proc_macro::TokenStream,
    item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let mut kind_attrs = kinded::Attrs::default();
    let parser = syn::meta::parser(|meta| {
        if meta.path.is_ident("name") {
            let value: syn::LitStr = meta.value()?.parse()?;
            kind_attrs.name.replace(value.value());
        } else if meta.path.is_ident("no_kind_fn") {
            kind_attrs.no_kind_fn = true;
        } else if meta.path.is_ident("kind_fn") {
            let value: syn::LitStr = meta.value()?.parse()?;
            kind_attrs.kind_fn.replace(value.value());
        } else {
            return Err(meta.error("invalid argument"));
        }
        Ok(())
    });
    parse_macro_input!(attrs_ts with parser);
    let item = parse_macro_input!(item as syn::DeriveInput);
    handle_syn_result(kinded::kinded_macro(kind_attrs, item))
}

#[cfg(feature = "sumtype")]
#[proc_macro_attribute]
pub fn sumtype(
    attrs_ts: proc_macro::TokenStream,
    item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let mut attrs = sum_type::Attrs {
        add_as: true,
        add_into: true,
        add_is: true,
        add_mut_as: true,
        add_try_into: true,
        add_try_into_impl: false,
        add_try_as: true,
        add_try_as_mut: true,
        add_from_impl: true,
    };
    let parser = syn::meta::parser(|meta| {
        attrs.add_syn(&meta)?;
        Ok(())
    });
    parse_macro_input!(attrs_ts with parser);
    let input = parse_macro_input!(item as syn::DeriveInput);
    sum_type::sumtype_attr(attrs, input).into()
}