system_harness_macros/
lib.rs

1use proc_macro::TokenStream;
2use syn::{
3    parse_macro_input, spanned::Spanned, AttrStyle, Attribute,
4    DeriveInput, LitStr
5};
6
7type Result<T> = std::result::Result<T, syn::Error>;
8
9mod properties;
10mod property_value;
11mod property_list;
12mod backends;
13
14#[proc_macro_derive(PropertyList)]
15pub fn property_list(input: TokenStream) -> TokenStream {
16    let derive_input = parse_macro_input!(input as DeriveInput);
17    match property_list::implement(&derive_input) {
18        Ok(props) => props.into(),
19        Err(err) => err.into_compile_error().into(),
20    }
21}
22
23#[proc_macro_derive(Backend)]
24pub fn backend(input: TokenStream) -> TokenStream {
25    let derive_input = parse_macro_input!(input as DeriveInput);
26    match backends::implement(&derive_input) {
27        Ok(props) => props.into(),
28        Err(err) => err.into_compile_error().into(),
29    }
30}
31
32#[proc_macro_derive(PropertyValue)]
33pub fn property_value(input: TokenStream) -> TokenStream {
34    let derive_input = parse_macro_input!(input as DeriveInput);
35    match property_value::implement(&derive_input) {
36        Ok(value) => value.into(),
37        Err(err) => err.into_compile_error().into(),
38    }
39}
40
41enum SerdeAttribute {
42    Flatten,
43    Rename(LitStr)
44}
45
46impl SerdeAttribute {
47
48    /// Check for relevant attributes
49    fn parse(attrs: &[Attribute]) -> Option<SerdeAttribute> {
50        let mut flatten = false;
51        let mut rename = None;
52        for attr in attrs {
53            match attr.style {
54                AttrStyle::Outer => match &attr.meta {
55                    syn::Meta::List(list) if list.path.is_ident("serde") => {
56                        let _ = attr.parse_nested_meta(|meta| {
57                            if meta.path.is_ident("flatten") {
58                                flatten = true;
59                            } else if meta.path.is_ident("rename") {
60                                let value = meta.value()?;
61                                let s: LitStr = value.parse()?;
62                                rename = Some(LitStr::new(&s.value(), attr.span()));
63                            }
64                            Ok(())
65                        });
66                    }
67                    _ => {}
68                },
69                _ => {}
70            };
71        }
72        if flatten {
73            Some(SerdeAttribute::Flatten)
74        } else if let Some(rename) = rename {
75            Some(SerdeAttribute::Rename(rename))
76        } else {
77            None
78        }
79    }
80
81}