indiscriminant_impl/
lib.rs

1use proc_macro::TokenStream;
2use proc_macro2::TokenStream as TokenStream2;
3
4use syn::{parse_macro_input, Data, DeriveInput, Expr, Lit};
5
6use indiscriminant_lib::indiscriminant_bits;
7use indiscriminant_lib::indiscriminant_byte_str;
8use indiscriminant_lib::indiscriminant_str;
9
10#[proc_macro_attribute]
11pub fn indiscriminant_str(args: TokenStream, input: TokenStream) -> TokenStream {
12    TokenStream::from(indiscriminant_str::indiscriminant_str(
13        TokenStream2::from(args),
14        TokenStream2::from(input),
15    ))
16}
17
18#[proc_macro_attribute]
19pub fn indiscriminant_byte_str(args: TokenStream, input: TokenStream) -> TokenStream {
20    TokenStream::from(indiscriminant_byte_str::indiscriminant_byte_str(
21        TokenStream2::from(args),
22        TokenStream2::from(input),
23    ))
24}
25
26#[proc_macro_attribute]
27pub fn indiscriminant_bits(args: TokenStream, input: TokenStream) -> TokenStream {
28    TokenStream::from(indiscriminant_bits::indiscriminant_bits(
29        TokenStream2::from(args),
30        TokenStream2::from(input),
31    ))
32}
33
34#[proc_macro_attribute]
35pub fn indiscriminant(args: TokenStream, input: TokenStream) -> TokenStream {
36    let input_cloned = input.clone();
37    // Parse enum body
38    let input_cloned = parse_macro_input!(input_cloned as DeriveInput);
39    let data = match input_cloned.data {
40        Data::Enum(data) => data,
41        _ => panic!("Attribute not applied to enum!"),
42    };
43    assert!(data.variants.len() > 0, "Enum is empty of any variants!");
44
45    let v = data.variants.iter().next().unwrap();
46
47    let literal = match &v.discriminant {
48        Some((_, Expr::Lit(literal))) => literal,
49        _ => panic!("Literal not found for first discriminant!"),
50    };
51
52    let args = TokenStream2::from(args);
53    let input = TokenStream2::from(input);
54    let result = match &literal.lit {
55        Lit::Str(_) => indiscriminant_str::indiscriminant_str(args, input),
56        Lit::ByteStr(_) => indiscriminant_byte_str::indiscriminant_byte_str(args, input),
57        Lit::Byte(_) | Lit::Int(_) => indiscriminant_bits::indiscriminant_bits(args, input),
58        _ => panic!("First literal is not string, byte-string, or integer!"),
59    };
60    TokenStream::from(result)
61}