diff --git a/satrs-core/src/resultcode.rs b/satrs-core/src/resultcode.rs index ab2edc4..885c7fb 100644 --- a/satrs-core/src/resultcode.rs +++ b/satrs-core/src/resultcode.rs @@ -25,12 +25,16 @@ impl ResultU16 { #[derive(Debug)] pub struct ResultU16Ext { pub name: &'static str, - pub result: ResultU16, + pub result: &'static ResultU16, pub info: &'static str, } impl ResultU16Ext { - pub const fn const_new(name: &'static str, result: ResultU16, info: &'static str) -> Self { + pub const fn const_new( + name: &'static str, + result: &'static ResultU16, + info: &'static str, + ) -> Self { Self { name, result, info } } } diff --git a/satrs-macros/src/lib.rs b/satrs-macros/src/lib.rs index 7bcd0cd..83e3e00 100644 --- a/satrs-macros/src/lib.rs +++ b/satrs-macros/src/lib.rs @@ -1,7 +1,105 @@ +use proc_macro2::{Ident, TokenStream}; +use quote::{format_ident, quote, ToTokens}; +use syn::spanned::Spanned; +use syn::{parse_macro_input, AttributeArgs, Item, Lit, LitStr, Meta, NestedMeta, Type}; + +#[derive(Default)] +struct ResultExtGenerator { + name_str: Option, + info_str: Option, +} + #[proc_macro_attribute] pub fn result( - _attr: proc_macro::TokenStream, + args: proc_macro::TokenStream, item: proc_macro::TokenStream, ) -> proc_macro::TokenStream { - item + let args = parse_macro_input!(args as AttributeArgs); + let input = parse_macro_input!(item as Item); + + dbg!("Arguments: {}", &args); + dbg!("Input: {}", &input); + let mut result_ext_generator = ResultExtGenerator::default(); + result_ext_generator.parse(args, input).into() +} + +impl ResultExtGenerator { + pub fn parse(&mut self, args: AttributeArgs, input: Item) -> TokenStream { + let mut output = input.to_token_stream(); + if let Err(e) = self.parse_args(args) { + output.extend(e.into_compile_error()); + return output; + } + match self.gen_ext_struct(input) { + Ok(ts) => output.extend(ts), + Err(e) => output.extend(e.into_compile_error()), + } + output + } + + pub fn parse_args(&mut self, args: AttributeArgs) -> syn::Result<()> { + for arg in args { + if let NestedMeta::Meta(Meta::NameValue(nvm)) = arg { + if let Some(path) = nvm.path.segments.first() { + if path.ident == "info" { + if let Lit::Str(str) = nvm.lit { + self.info_str = Some(str); + } else { + return Err(syn::Error::new( + nvm.lit.span(), + "Only literal strings are allowed as information", + )); + } + } else { + return Err(syn::Error::new( + path.span(), + format!( + "Unknown attribute argument name {}", + path.ident + ), + )); + } + } + } + } + Ok(()) + } + + pub fn gen_ext_struct(&mut self, input: Item) -> syn::Result { + if let Item::Const(const_item) = &input { + self.name_str = Some(const_item.ident.clone()); + if let Type::Path(p) = &const_item.ty.as_ref() { + let mut valid_type_found = false; + for seg in &p.path.segments { + if seg.ident == "ResultU16" { + valid_type_found = true; + } + } + if !valid_type_found { + return Err(syn::Error::new( + p.span(), + "Can only be applied on items of type ResultU16", + )); + } + } + } else { + return Err(syn::Error::new( + input.span(), + "Only const items are allowed to be use with this attribute", + )); + } + let result_code_name = self.name_str.to_owned().unwrap(); + let name_as_str = result_code_name.to_string(); + let gen_struct_name = format_ident!("{}_EXT", result_code_name); + let info_str = self.info_str.to_owned().unwrap(); + let gen_struct = quote! { + const #gen_struct_name: satrs_core::resultcode::ResultU16Ext = satrs_core::resultcode::ResultU16Ext { + name: #name_as_str, + result: &#result_code_name, + info: #info_str + }; + }; + Ok(gen_struct) + //Ok(TokenStream::new()) + } } diff --git a/satrs-macros/src/main.rs b/satrs-macros/src/main.rs new file mode 100644 index 0000000..7eb903a --- /dev/null +++ b/satrs-macros/src/main.rs @@ -0,0 +1,7 @@ +use satrs_core::resultcode::ResultU16; +use satrs_macros::*; + +#[result(info = "This is a test result where the first parameter is foo")] +const _TEST_RESULT: ResultU16 = ResultU16::const_new(0, 1); + +fn main() {} diff --git a/satrs-macros/tests/basic.rs b/satrs-macros/tests/basic.rs index f9a8210..e224e4a 100644 --- a/satrs-macros/tests/basic.rs +++ b/satrs-macros/tests/basic.rs @@ -1,7 +1,7 @@ use satrs_core::resultcode::ResultU16; use satrs_macros::*; -#[result] +#[result(info = "This is a test result where the first parameter is foo")] const TEST_RESULT: ResultU16 = ResultU16::const_new(0, 1); fn main() {} diff --git a/satrs-macros/tests/group_in_enum.rs b/satrs-macros/tests/group_in_enum.rs new file mode 100644 index 0000000..ecc71dc --- /dev/null +++ b/satrs-macros/tests/group_in_enum.rs @@ -0,0 +1,12 @@ +use satrs_core::resultcode::ResultU16; +use satrs_macros::*; + +pub enum GroupIds { + Group0 = 0, + Group1 = 1, +} + +#[result(info = "This is a test result where the first parameter is foo")] +const TEST_RESULT: ResultU16 = ResultU16::const_new(GroupIds::Group0 as u8, 1); + +fn main() {} diff --git a/satrs-macros/tests/tests.rs b/satrs-macros/tests/tests.rs index 71b63af..d1b72fe 100644 --- a/satrs-macros/tests/tests.rs +++ b/satrs-macros/tests/tests.rs @@ -2,4 +2,6 @@ fn tests() { let t = trybuild::TestCases::new(); t.pass("tests/basic.rs"); + //t.pass("tests/verify_gen_struct.rs"); + //t.pass("tests/group_in_enum.rs"); } diff --git a/satrs-macros/tests/verify_gen_struct.rs b/satrs-macros/tests/verify_gen_struct.rs new file mode 100644 index 0000000..e224e4a --- /dev/null +++ b/satrs-macros/tests/verify_gen_struct.rs @@ -0,0 +1,7 @@ +use satrs_core::resultcode::ResultU16; +use satrs_macros::*; + +#[result(info = "This is a test result where the first parameter is foo")] +const TEST_RESULT: ResultU16 = ResultU16::const_new(0, 1); + +fn main() {}