From nobody Sun Sep 28 17:06:19 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1758706396; cv=none; d=zohomail.com; s=zohoarc; b=RjKmr14GZlPe3RqxqWf48HPvgFEewAFa9/ENVnLRUab2k/YU1rPrmtjMMU656ofcqEbty3qQKNnxmq7bT4njZSKidgwWt3SqlhFtBg1pU41+C6Syei/DV0ENDd0HQqqJLFBiwvPBV6S2ccGSb+7/A7KU1P0dqFfcrRw5R7jeEOs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1758706396; h=Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To:Cc; bh=i/j0P/MSV+X5BLJW2jx5BBKNa2M5lI05wnZcxCRbxSk=; b=OVWIpEBpFvPUu7VjTUXIYINZZW0qKVeDCTN4GinfJxVmzTHVQa7QpEzQxy3iaiN/nP2nbqKRPKX50fTrJrL9QeDZBqLTCf+HGV5ifObRKLXo6vEsPE9Iz2MHnzj7iOkMGBzPEOLkDqohMMYEghsne7pkMNT5N9f7UGx8yqkZ43c= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758706396344416.82260229622364; Wed, 24 Sep 2025 02:33:16 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1LoT-0004ff-U4; Wed, 24 Sep 2025 05:29:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1LoS-0004dY-9E for qemu-devel@nongnu.org; Wed, 24 Sep 2025 05:29:24 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1LoP-0004me-K0 for qemu-devel@nongnu.org; Wed, 24 Sep 2025 05:29:24 -0400 Received: from mail-ej1-f71.google.com (mail-ej1-f71.google.com [209.85.218.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-210-7XHbMKErPqySi057Tk8vvQ-1; Wed, 24 Sep 2025 05:29:17 -0400 Received: by mail-ej1-f71.google.com with SMTP id a640c23a62f3a-b2f989de76eso73893966b.1 for ; Wed, 24 Sep 2025 02:29:16 -0700 (PDT) Received: from [192.168.10.48] ([176.206.127.188]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b2ba267f745sm720317166b.33.2025.09.24.02.29.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 24 Sep 2025 02:29:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758706158; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=i/j0P/MSV+X5BLJW2jx5BBKNa2M5lI05wnZcxCRbxSk=; b=e57obKe10H4g6OtLrJIkU5K5x7Jb7LO773GgveJfHizi+W+u4TkrS21YD32LiwillxPTQ5 znX7//Lh4xTjfJOb9CPUv19oMGoX7EIDuE5xsu05OxKnyUuIOomEv26dq6ttMNHKsqfiz6 7YppdldRViuHhSZxalsRB6CHHAytmh4= X-MC-Unique: 7XHbMKErPqySi057Tk8vvQ-1 X-Mimecast-MFC-AGG-ID: 7XHbMKErPqySi057Tk8vvQ_1758706156 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758706155; x=1759310955; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=i/j0P/MSV+X5BLJW2jx5BBKNa2M5lI05wnZcxCRbxSk=; b=P5dpGzEIkXQylxdIo26kHarcbh3S/aoBrpAbxomZbrFDEQA3qK/jFjueiF2dAj/UEk z2xhzc2l/Fecf28Hjeku8EM09Sj5oGLA+MQqf9Bg3osEc0qi1Lh7zYzPjGNmerD6u5X/ 9Jv4Pj+1uRAEtB7hrbZuZ/Oi1xW1EgSwYk3+T2hPlH2z+mZQGfhewKfFCbaaucPRCgWy 3vjfJylxD5R1Wgls1d+X+EufEENueq+Mg3KtDpB/cQ5wO8KFhG1otHwDVLCtdjsCE3G4 PWHP4vrv3n7SVBWc0akNBIdc3uCuC2lfObMolYMdeEAEmxv4u49ltgs7dWtZ5atvveMU UEVg== X-Gm-Message-State: AOJu0Yw/PwcGmouXHxYUnR2YBcSYiDyhhXJYXfHVf8hoziShwbP3NrJk HoN+DH0L14PgGgAAxG/Lj+Jrca0heglkan/BNamVtoAFZleSkO86DCdTfu0a3O+P+0ooVB4SYWr lttBYL3AghtDO6FXpSROtzDNi4K6XmmLF5JV0Ne/Tt/LtPXjn8cHuqP5PkQBjyJa4EoqrEXfmOT mXitUxHDn5dpb/8z4kMedEGYOq/rePNRLsAQ3mszEC X-Gm-Gg: ASbGncvKIjVzmDndnMEVCdq7wc4A9AsLjRcFX8uqCYjRudmuJIaBkNzOQM23cPU0puv zOJZT8GAVecfS7CYMijoVbgTu79KKP3/4ItEmxJLal7CbaHLD+GNuQiMnuILHOpHDEoU2DcyWvh zc+uGmAejs8UdCmbMHi9ROIooxByPE10/q2u/oLP9N60KZXykzoorPuDAu1GVzMthNOWyQZxU16 n5w9RP2vJfx4qJVwblP03h432DiOJs847HiU7HF/6xzzfjj7CYl8/tqJCg4DzBBbHAsnd7OEmVR OaMKbwwvM6Nf8DK6SeemduxfWM2HPQ5VI2q+bTQ5ll2EpYeNPsjdte4kLDvJFrkzTENPbKJHG9C CK85vQOuUg/GJLWcjCIzXSiWZVn/AbA2fOEfIqYQCwAP7QQ== X-Received: by 2002:a17:907:d1a:b0:b2a:10a3:7112 with SMTP id a640c23a62f3a-b32caf90a7emr175817066b.24.1758706154963; Wed, 24 Sep 2025 02:29:14 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGMlv3+YnITlkTGPOSxHh5xSGdLNPdYRVziQLvktkLpNKacbi9KQjjECAXYQhgJxXfHsYOOKQ== X-Received: by 2002:a17:907:d1a:b0:b2a:10a3:7112 with SMTP id a640c23a62f3a-b32caf90a7emr175776166b.24.1758706146742; Wed, 24 Sep 2025 02:29:06 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PULL 06/29] rust: qemu-macros: switch #[property] parsing to use combinators Date: Wed, 24 Sep 2025 11:28:26 +0200 Message-ID: <20250924092850.42047-7-pbonzini@redhat.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250924092850.42047-1-pbonzini@redhat.com> References: <20250924092850.42047-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -24 X-Spam_score: -2.5 X-Spam_bar: -- X-Spam_report: (-2.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.442, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1758706397169116600 Content-Type: text/plain; charset="utf-8" Since we are going to add more attribute parsing for high-level migration state macros, use the attrs crate instead of a handwritten parser for device properties as well. Signed-off-by: Paolo Bonzini --- rust/Cargo.lock | 11 +++++ rust/qemu-macros/src/lib.rs | 86 ++++++++++++++--------------------- rust/qemu-macros/src/tests.rs | 8 ++-- 3 files changed, 49 insertions(+), 56 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index eea928621a7..8315f98c46f 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -14,6 +14,16 @@ version =3D "1.2.7" source =3D "registry+https://github.com/rust-lang/crates.io-index" checksum =3D "c84fc003e338a6f69fbd4f7fe9f92b535ff13e9af8997f3b14b6ddff8b1d= f46d" =20 +[[package]] +name =3D "attrs" +version =3D "0.2.9" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "2a207d40f43de65285f3de0509bb6cb16bc46098864fce957122bbacce32= 7e5f" +dependencies =3D [ + "proc-macro2", + "syn", +] + [[package]] name =3D "bilge" version =3D "0.2.0" @@ -188,6 +198,7 @@ dependencies =3D [ name =3D "qemu_macros" version =3D "0.1.0" dependencies =3D [ + "attrs", "proc-macro2", "quote", "syn", diff --git a/rust/qemu-macros/src/lib.rs b/rust/qemu-macros/src/lib.rs index 830b4326985..7ab18061776 100644 --- a/rust/qemu-macros/src/lib.rs +++ b/rust/qemu-macros/src/lib.rs @@ -3,10 +3,14 @@ // SPDX-License-Identifier: GPL-2.0-or-later =20 use proc_macro::TokenStream; -use quote::{quote, quote_spanned, ToTokens}; +use quote::{quote, quote_spanned}; use syn::{ - parse::Parse, parse_macro_input, parse_quote, punctuated::Punctuated, = spanned::Spanned, - token::Comma, Data, DeriveInput, Error, Field, Fields, FieldsUnnamed, = Ident, Meta, Path, Token, + parse::{Parse, ParseStream}, + parse_macro_input, parse_quote, + punctuated::Punctuated, + spanned::Spanned, + token::Comma, + Attribute, Data, DeriveInput, Error, Field, Fields, FieldsUnnamed, Ide= nt, Meta, Path, Token, Variant, }; mod bits; @@ -159,61 +163,37 @@ enum DevicePropertyName { Str(syn::LitStr), } =20 -#[derive(Debug)] +impl Parse for DevicePropertyName { + fn parse(input: ParseStream<'_>) -> syn::Result { + let lo =3D input.lookahead1(); + if lo.peek(syn::LitStr) { + Ok(Self::Str(input.parse()?)) + } else if lo.peek(syn::LitCStr) { + Ok(Self::CStr(input.parse()?)) + } else { + Err(lo.error()) + } + } +} + +#[derive(Default, Debug)] struct DeviceProperty { rename: Option, defval: Option, } =20 -impl Parse for DeviceProperty { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let _: syn::Token![#] =3D input.parse()?; - let bracketed; - _ =3D syn::bracketed!(bracketed in input); - let attribute =3D bracketed.parse::()?; - debug_assert_eq!(&attribute.to_string(), "property"); - let mut retval =3D Self { - rename: None, - defval: None, - }; - let content; - _ =3D syn::parenthesized!(content in bracketed); - while !content.is_empty() { - let value: syn::Ident =3D content.parse()?; - if value =3D=3D "rename" { - let _: syn::Token![=3D] =3D content.parse()?; - if retval.rename.is_some() { - return Err(syn::Error::new( - value.span(), - "`rename` can only be used at most once", - )); - } - if content.peek(syn::LitStr) { - retval.rename =3D Some(DevicePropertyName::Str(content= .parse::()?)); - } else { - retval.rename =3D - Some(DevicePropertyName::CStr(content.parse::()?)); - } - } else if value =3D=3D "default" { - let _: syn::Token![=3D] =3D content.parse()?; - if retval.defval.is_some() { - return Err(syn::Error::new( - value.span(), - "`default` can only be used at most once", - )); - } - retval.defval =3D Some(content.parse()?); - } else { - return Err(syn::Error::new( - value.span(), - format!("unrecognized field `{value}`"), - )); - } +impl DeviceProperty { + fn parse_from(&mut self, a: &Attribute) -> syn::Result<()> { + use attrs::{set, with, Attrs}; + let mut parser =3D Attrs::new(); + parser.once("rename", with::eq(set::parse(&mut self.rename))); + parser.once("default", with::eq(set::parse(&mut self.defval))); + a.parse_args_with(&mut parser) + } =20 - if !content.is_empty() { - let _: syn::Token![,] =3D content.parse()?; - } - } + fn parse(a: &Attribute) -> syn::Result { + let mut retval =3D Self::default(); + retval.parse_from(a)?; Ok(retval) } } @@ -235,7 +215,7 @@ fn derive_device_or_error(input: DeriveInput) -> Result= , Error>>()?; let name =3D &input.ident; diff --git a/rust/qemu-macros/src/tests.rs b/rust/qemu-macros/src/tests.rs index 9ab7eab7f37..00a106612fc 100644 --- a/rust/qemu-macros/src/tests.rs +++ b/rust/qemu-macros/src/tests.rs @@ -60,7 +60,7 @@ struct DummyState { migrate_clock: bool, } }, - "unrecognized field `defalt`" + "Expected one of `default` or `rename`" ); // Check that repeated attributes are not allowed: derive_compile_fail!( @@ -73,7 +73,8 @@ struct DummyState { migrate_clock: bool, } }, - "`rename` can only be used at most once" + "Duplicate argument", + "Already used here", ); derive_compile_fail!( derive_device_or_error, @@ -85,7 +86,8 @@ struct DummyState { migrate_clock: bool, } }, - "`default` can only be used at most once" + "Duplicate argument", + "Already used here", ); // Check that the field name is preserved when `rename` isn't used: derive_compile!( --=20 2.51.0