1use syn::{parse_macro_input, ItemImpl};
2
3mod fac;
4mod noise;
5mod residual;
6mod robust;
7mod variable;
8
9enum BoxedTypes {
10 Residual,
11 Variable,
12 Noise,
13 Robust,
14}
15
16fn check_type(input: &ItemImpl) -> syn::Result<BoxedTypes> {
17 let err = syn::Error::new_spanned(input, "Missing trait");
18 let result = &input
19 .trait_
20 .as_ref()
21 .ok_or(err.clone())?
22 .1
23 .segments
24 .last()
25 .ok_or(err)?
26 .ident
27 .to_string();
28
29 if result.contains("Residual") {
30 Ok(BoxedTypes::Residual)
31 } else if result.contains("Variable") {
32 Ok(BoxedTypes::Variable)
33 } else if result.contains("Noise") {
34 Ok(BoxedTypes::Noise)
35 } else if result.contains("Robust") {
36 Ok(BoxedTypes::Robust)
37 } else {
38 Err(syn::Error::new_spanned(input, "Not a valid trait"))
39 }
40}
41
42#[proc_macro_attribute]
43pub fn mark(
44 _args: proc_macro::TokenStream,
45 input: proc_macro::TokenStream,
46) -> proc_macro::TokenStream {
47 let input = syn::parse_macro_input!(input as ItemImpl);
48
49 let trait_type = match check_type(&input) {
50 Ok(syntax_tree) => syntax_tree,
51 Err(err) => return err.to_compile_error().into(),
52 };
53
54 match trait_type {
55 BoxedTypes::Residual => residual::mark(input),
56 BoxedTypes::Variable => variable::mark(input),
57 BoxedTypes::Noise => noise::mark(input),
58 BoxedTypes::Robust => robust::mark(input),
59 }
60 .into()
61}
62
63#[proc_macro]
64pub fn fac(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
65 let factor = parse_macro_input!(input as fac::Factor);
66
67 fac::fac(factor).into()
68}