decimal_core/
lib.rs

1use quote::{quote, ToTokens};
2use syn::parse_macro_input;
3
4mod base;
5mod big_ops;
6mod by_number;
7mod checked_ops;
8mod factories;
9mod ops;
10mod others;
11mod structs;
12mod utils;
13
14use structs::DecimalCharacteristics;
15
16use utils::string_to_ident;
17
18#[proc_macro_attribute]
19pub fn decimal(
20    attr: proc_macro::TokenStream,
21    item: proc_macro::TokenStream,
22) -> proc_macro::TokenStream {
23    let args_str = attr.to_string();
24    let args: Vec<&str> = args_str.split(',').collect();
25
26    let parsed_scale = args[0].parse::<u8>().unwrap_or(0);
27
28    let big_type = match args.len() {
29        1 => string_to_ident("", "U256"),
30        2 => string_to_ident("", args[1].trim()),
31        _ => panic!("decimal: invalid number of parameters"),
32    };
33
34    assert!(parsed_scale <= 38, "scale too big");
35
36    let k = item.clone();
37    let decimal_struct = parse_macro_input!(k as syn::ItemStruct);
38
39    let fields = decimal_struct.fields;
40    let first_field = fields.iter().next().unwrap();
41
42    let underlying_type =
43        string_to_ident("", first_field.ty.to_token_stream().to_string().as_str());
44
45    let field_name = match first_field.ident.clone() {
46        Some(ident) => quote! {#ident},
47        None => quote! {0},
48    };
49
50    let struct_name = decimal_struct.ident;
51
52    let characteristics = DecimalCharacteristics {
53        struct_name: struct_name.clone(),
54        field_name: field_name.clone(),
55        underlying_type: underlying_type.clone(),
56        big_type: big_type.clone(),
57        scale: parsed_scale,
58    };
59
60    let mut result = proc_macro::TokenStream::from(quote! {
61        // #[derive(Default, std::fmt::Debug, Clone, Copy, PartialEq, )]
62    });
63
64    result.extend(item.clone());
65
66    result.extend(base::generate_base(characteristics.clone()));
67    result.extend(ops::generate_ops(characteristics.clone()));
68    result.extend(big_ops::generate_big_ops(characteristics.clone()));
69    result.extend(by_number::generate_by_number(characteristics.clone()));
70    result.extend(others::generate_others(characteristics.clone()));
71    result.extend(factories::generate_factories(characteristics.clone()));
72    result.extend(checked_ops::generate_checked_ops(characteristics.clone()));
73
74    result.extend(proc_macro::TokenStream::from(quote! {
75        impl #struct_name {
76            pub fn is_zero(self) -> bool {
77                self.#field_name == #underlying_type::try_from(0).unwrap()
78            }
79        }
80    }));
81
82    result
83}