From bd7fdac2d7fdaa9892a06e75868d87b38b5ed9e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 24 Apr 2024 13:09:22 +0200 Subject: [PATCH] fix(macro): support `#[repr(align(N))]` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- volatile-macro/src/volatile.rs | 47 ++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/volatile-macro/src/volatile.rs b/volatile-macro/src/volatile.rs index 2bcc104..ecff9f6 100644 --- a/volatile-macro/src/volatile.rs +++ b/volatile-macro/src/volatile.rs @@ -1,7 +1,8 @@ use quote::format_ident; +use syn::punctuated::Punctuated; use syn::{ - parse_quote, Attribute, Fields, Ident, Item, ItemImpl, ItemStruct, ItemTrait, Path, Result, - Signature, Visibility, + parse_quote, Attribute, Fields, Ident, Item, ItemImpl, ItemStruct, ItemTrait, Meta, Path, + Result, Signature, Token, Visibility, }; fn validate_input(input: &ItemStruct) -> Result<()> { @@ -22,9 +23,13 @@ fn validate_input(input: &ItemStruct) -> Result<()> { let mut valid_repr = false; for attr in &input.attrs { if attr.path().is_ident("repr") { - let ident = attr.parse_args::()?; - if ident == "C" || ident == "transparent" { - valid_repr = true; + let nested = attr.parse_args_with(Punctuated::::parse_terminated)?; + for meta in nested { + if let Meta::Path(path) = meta { + if path.is_ident("C") || path.is_ident("transparent") { + valid_repr = true; + } + } } } } @@ -212,4 +217,36 @@ mod tests { Ok(()) } + + #[test] + fn test_align() -> Result<()> { + let input = parse_quote! { + #[repr(C, align(8))] + #[derive(VolatileFieldAccess)] + pub struct DeviceConfig {} + }; + + let result = derive_volatile(input)?; + + let expected_trait = quote! { + #[allow(non_camel_case_types)] + pub trait DeviceConfigVolatileFieldAccess<'a> {} + }; + + let expected_impl = quote! { + #[automatically_derived] + impl<'a> DeviceConfigVolatileFieldAccess<'a> for ::volatile::VolatilePtr<'a, DeviceConfig, ::volatile::access::ReadWrite> {} + }; + + assert_eq!( + expected_trait.to_string(), + result[0].to_token_stream().to_string() + ); + assert_eq!( + expected_impl.to_string(), + result[1].to_token_stream().to_string() + ); + + Ok(()) + } }