satrs_mib_codegen/
lib.rs

1use quote::{format_ident, quote, ToTokens};
2use syn::{parse_macro_input, ItemConst, LitStr};
3
4/// This macro can be used to automatically generate introspection information for return codes.
5///
6/// For example, it can be applied to types like the
7/// [`satrs_mib::res_code::ResultU16`](https://docs.rs/satrs-mib/latest/satrs_mib/res_code/struct.ResultU16.html#) type
8/// to automatically generate
9/// [`satrs_mib::res_code::ResultU16Info`](https://docs.rs/satrs-mib/latest/satrs_mib/res_code/struct.ResultU16Info.html)
10/// instances. These instances can then be used for tasks like generating CSVs or YAML files with
11/// the list of all result codes. This information is valuable for both operators and developers.
12#[proc_macro_attribute]
13pub fn resultcode(
14    args: proc_macro::TokenStream,
15    item: proc_macro::TokenStream,
16) -> proc_macro::TokenStream {
17    // Handle attributes first.
18    let mut info_str: Option<LitStr> = None;
19    let res_code_parser = syn::meta::parser(|meta| {
20        if meta.path.is_ident("info") {
21            info_str = Some(meta.value()?.parse()?);
22            Ok(())
23        } else {
24            Err(meta.error("unsupported property for resultcode attribute"))
25        }
26    });
27    parse_macro_input!(args with res_code_parser);
28    let item = parse_macro_input!(item as ItemConst);
29
30    // Generate additional generated info struct used for introspection.
31    let result_code_name = &item.ident;
32    let name_as_str = result_code_name.to_string();
33    let gen_struct_name = format_ident!("{}_EXT", result_code_name);
34    let info_str = info_str.map_or(String::from(""), |v| v.value());
35    // TODO: Group string
36    let generated_struct = quote! {
37        const #gen_struct_name: satrs_mib::res_code::ResultU16Info =
38            satrs_mib::res_code::ResultU16Info::const_new(
39                #name_as_str,
40                &#result_code_name,
41                "",
42                #info_str
43            );
44    };
45
46    // The input constant returncode is written to the output in any case.
47    let mut output = item.to_token_stream();
48    output.extend(generated_struct);
49    output.into()
50}