From 465a4b80e2afd93f2eb4c9f55233788ebfb47ac0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 2 May 2025 11:42:48 +0200 Subject: rust: qemu_api_macros: make pattern matching more readable and efficient "let ... else" is useful when visiting syntax trees; it avoids multiple levels of indentation and places the error close to the pattern. While at it, use "ref" to avoid moving the syntax tree objects. Reviewed-by: Zhao Liu Signed-off-by: Paolo Bonzini --- rust/qemu-api-macros/src/lib.rs | 84 ++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 47 deletions(-) (limited to 'rust/qemu-api-macros') diff --git a/rust/qemu-api-macros/src/lib.rs b/rust/qemu-api-macros/src/lib.rs index eda0d46..0bffd26 100644 --- a/rust/qemu-api-macros/src/lib.rs +++ b/rust/qemu-api-macros/src/lib.rs @@ -16,50 +16,41 @@ fn get_fields<'a>( input: &'a DeriveInput, msg: &str, ) -> Result<&'a Punctuated, MacroError> { - if let Data::Struct(s) = &input.data { - if let Fields::Named(fs) = &s.fields { - Ok(&fs.named) - } else { - Err(MacroError::Message( - format!("Named fields required for {}", msg), - input.ident.span(), - )) - } - } else { - Err(MacroError::Message( + let Data::Struct(ref s) = &input.data else { + return Err(MacroError::Message( format!("Struct required for {}", msg), input.ident.span(), - )) - } + )); + }; + let Fields::Named(ref fs) = &s.fields else { + return Err(MacroError::Message( + format!("Named fields required for {}", msg), + input.ident.span(), + )); + }; + Ok(&fs.named) } fn get_unnamed_field<'a>(input: &'a DeriveInput, msg: &str) -> Result<&'a Field, MacroError> { - if let Data::Struct(s) = &input.data { - let unnamed = match &s.fields { - Fields::Unnamed(FieldsUnnamed { - unnamed: ref fields, - .. - }) => fields, - _ => { - return Err(MacroError::Message( - format!("Tuple struct required for {}", msg), - s.fields.span(), - )) - } - }; - if unnamed.len() != 1 { - return Err(MacroError::Message( - format!("A single field is required for {}", msg), - s.fields.span(), - )); - } - Ok(&unnamed[0]) - } else { - Err(MacroError::Message( + let Data::Struct(ref s) = &input.data else { + return Err(MacroError::Message( format!("Struct required for {}", msg), input.ident.span(), - )) + )); + }; + let Fields::Unnamed(FieldsUnnamed { ref unnamed, .. }) = &s.fields else { + return Err(MacroError::Message( + format!("Tuple struct required for {}", msg), + s.fields.span(), + )); + }; + if unnamed.len() != 1 { + return Err(MacroError::Message( + format!("A single field is required for {}", msg), + s.fields.span(), + )); } + Ok(&unnamed[0]) } fn is_c_repr(input: &DeriveInput, msg: &str) -> Result<(), MacroError> { @@ -210,20 +201,19 @@ fn get_repr_uN(input: &DeriveInput, msg: &str) -> Result { } fn get_variants(input: &DeriveInput) -> Result<&Punctuated, MacroError> { - if let Data::Enum(e) = &input.data { - if let Some(v) = e.variants.iter().find(|v| v.fields != Fields::Unit) { - return Err(MacroError::Message( - "Cannot derive TryInto for enum with non-unit variants.".to_string(), - v.fields.span(), - )); - } - Ok(&e.variants) - } else { - Err(MacroError::Message( + let Data::Enum(ref e) = &input.data else { + return Err(MacroError::Message( "Cannot derive TryInto for union or struct.".to_string(), input.ident.span(), - )) + )); + }; + if let Some(v) = e.variants.iter().find(|v| v.fields != Fields::Unit) { + return Err(MacroError::Message( + "Cannot derive TryInto for enum with non-unit variants.".to_string(), + v.fields.span(), + )); } + Ok(&e.variants) } #[rustfmt::skip::macros(quote)] -- cgit v1.1 From b134a09ffab3b918979007cf40f603e5b54ed597 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 2 May 2025 10:35:49 +0200 Subject: rust: remove offset_of replacement Reviewed-by: Manos Pitsidianakis Signed-off-by: Paolo Bonzini --- rust/qemu-api-macros/src/lib.rs | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) (limited to 'rust/qemu-api-macros') diff --git a/rust/qemu-api-macros/src/lib.rs b/rust/qemu-api-macros/src/lib.rs index 0bffd26..dc14cac 100644 --- a/rust/qemu-api-macros/src/lib.rs +++ b/rust/qemu-api-macros/src/lib.rs @@ -6,7 +6,7 @@ use proc_macro::TokenStream; use quote::quote; use syn::{ parse_macro_input, parse_quote, punctuated::Punctuated, spanned::Spanned, token::Comma, Data, - DeriveInput, Field, Fields, FieldsUnnamed, Ident, Meta, Path, Token, Type, Variant, Visibility, + DeriveInput, Field, Fields, FieldsUnnamed, Ident, Meta, Path, Token, Variant, }; mod utils; @@ -151,33 +151,6 @@ pub fn derive_opaque(input: TokenStream) -> TokenStream { TokenStream::from(expanded) } -#[rustfmt::skip::macros(quote)] -fn derive_offsets_or_error(input: DeriveInput) -> Result { - is_c_repr(&input, "#[derive(offsets)]")?; - - let name = &input.ident; - let fields = get_fields(&input, "#[derive(offsets)]")?; - let field_names: Vec<&Ident> = fields.iter().map(|f| f.ident.as_ref().unwrap()).collect(); - let field_types: Vec<&Type> = fields.iter().map(|f| &f.ty).collect(); - let field_vis: Vec<&Visibility> = fields.iter().map(|f| &f.vis).collect(); - - Ok(quote! { - ::qemu_api::with_offsets! { - struct #name { - #(#field_vis #field_names: #field_types,)* - } - } - }) -} - -#[proc_macro_derive(offsets)] -pub fn derive_offsets(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as DeriveInput); - let expanded = derive_offsets_or_error(input).unwrap_or_else(Into::into); - - TokenStream::from(expanded) -} - #[allow(non_snake_case)] fn get_repr_uN(input: &DeriveInput, msg: &str) -> Result { let repr = input.attrs.iter().find(|attr| attr.path().is_ident("repr")); -- cgit v1.1 From c6b04613bdc9a911c0fbe7c114a421991721f878 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 5 May 2025 12:19:55 +0200 Subject: rust: clippy: enable uninlined_format_args lint Signed-off-by: Paolo Bonzini --- rust/qemu-api-macros/src/lib.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'rust/qemu-api-macros') diff --git a/rust/qemu-api-macros/src/lib.rs b/rust/qemu-api-macros/src/lib.rs index dc14cac..f97449b 100644 --- a/rust/qemu-api-macros/src/lib.rs +++ b/rust/qemu-api-macros/src/lib.rs @@ -18,13 +18,13 @@ fn get_fields<'a>( ) -> Result<&'a Punctuated, MacroError> { let Data::Struct(ref s) = &input.data else { return Err(MacroError::Message( - format!("Struct required for {}", msg), + format!("Struct required for {msg}"), input.ident.span(), )); }; let Fields::Named(ref fs) = &s.fields else { return Err(MacroError::Message( - format!("Named fields required for {}", msg), + format!("Named fields required for {msg}"), input.ident.span(), )); }; @@ -34,19 +34,19 @@ fn get_fields<'a>( fn get_unnamed_field<'a>(input: &'a DeriveInput, msg: &str) -> Result<&'a Field, MacroError> { let Data::Struct(ref s) = &input.data else { return Err(MacroError::Message( - format!("Struct required for {}", msg), + format!("Struct required for {msg}"), input.ident.span(), )); }; let Fields::Unnamed(FieldsUnnamed { ref unnamed, .. }) = &s.fields else { return Err(MacroError::Message( - format!("Tuple struct required for {}", msg), + format!("Tuple struct required for {msg}"), s.fields.span(), )); }; if unnamed.len() != 1 { return Err(MacroError::Message( - format!("A single field is required for {}", msg), + format!("A single field is required for {msg}"), s.fields.span(), )); } @@ -60,7 +60,7 @@ fn is_c_repr(input: &DeriveInput, msg: &str) -> Result<(), MacroError> { Ok(()) } else { Err(MacroError::Message( - format!("#[repr(C)] required for {}", msg), + format!("#[repr(C)] required for {msg}"), input.ident.span(), )) } @@ -73,7 +73,7 @@ fn is_transparent_repr(input: &DeriveInput, msg: &str) -> Result<(), MacroError> Ok(()) } else { Err(MacroError::Message( - format!("#[repr(transparent)] required for {}", msg), + format!("#[repr(transparent)] required for {msg}"), input.ident.span(), )) } @@ -168,7 +168,7 @@ fn get_repr_uN(input: &DeriveInput, msg: &str) -> Result { } Err(MacroError::Message( - format!("#[repr(u8/u16/u32/u64) required for {}", msg), + format!("#[repr(u8/u16/u32/u64) required for {msg}"), input.ident.span(), )) } -- cgit v1.1