On 9/25/25 14:35, Zhao Liu wrote:
+/// #[derive(ToMigrationState)]
  /// pub struct DeviceRegs {
  ///     status: u32,
  /// }
+/// # unsafe impl VMState for DeviceRegsMigration {
+/// #     const BASE: VMStateField = ::common::Zeroable::ZERO;
+/// # }

Outdated comment? Looks like the DeviceRegsMigration definition is
missing.

It's defined by the #[derive(ToMigrationState)].

the below conversion is ugly:>
#[property(rename = "msi", bit = HPET_FLAG_MSI_SUPPORT_SHIFT as u8, default = 
false)]

conversion should happen within the macro parsing process. But unfortunately,
try_into() is not const, maybe I could do this for bit property:

diff --git a/rust/qemu-macros/src/lib.rs b/rust/qemu-macros/src/lib.rs
index c459f9bcb42f..e67df57c3712 100644
--- a/rust/qemu-macros/src/lib.rs
+++ b/rust/qemu-macros/src/lib.rs
@@ -275,7 +275,10 @@ macro_rules! str_to_c_str {
                  name: ::std::ffi::CStr::as_ptr(#prop_name),
                  info: #qdev_prop,
                  offset: ::core::mem::offset_of!(#name, #field_name) as isize,
-                bitnr: #bitnr,
+                bitnr: {
+                    const _: () = assert!(#bitnr <= u8::MAX as _, "bit exceeds u8 
range");
+                    #bitnr as u8
+                },
                  set_default: #set_default,
                  defval: ::hwcore::bindings::Property__bindgen_ty_1 { u: 
#defval as u64 },
                  ..::common::Zeroable::ZERO

Good idea (also testing >= 0 is needed). "const { assert!(...); }" is even simpler.

+/// - `#[migration_state(clone)]` - Clones the field value.

How about emphasizing the use case?

"Clones the field value, especially for the types don't implement `Copy`."

I don't have a use case yet to be honest, but at the same time I want to help potential device authors and remove the need to muck with the macro.

+/// Fields without any attributes use `ToMigrationState` recursively; note that
+/// this is a simple copy for types that implement `Copy`.
+///
+/// # Attribute compatibility
+///
+/// - `omit` cannot be used with any other attributes
+/// - only one of `into(Type)`, `try_into(Type)` can be used, but they can be
+///   coupled with `clone`.
+///

...

The implementation of the entire macro is great.

Thanks. :) It's indeed pretty easy to follow, and I like procedural macro code that is simple but powerful.

The attrs crate also helps a lot!

+#[test]
+fn test_derive_to_migration_state() {

...

+        quote! {
+            #[derive(Default)]
+            pub struct CustomMigration {
+                pub shared_data: String,
+                pub converted_field: Cow<'static, str>,
+                pub fallible_field: i8,
+                pub nested_field: <NestedStruct as ToMigrationState>::Migrated,
+                pub simple_field: <u32 as ToMigrationState>::Migrated,
+            }

In the production code, CustomMigration still needs to implement VMState
trait, so that String & Cow<'static, str> also need to implement VMState
trait. This seems like the thing that we are currently missing.

Or more simply they're not chosen well. :) For the documentation I will think of better types.

For test, it's enough to show how the macro works.

Yes, for testing it's a lesser deal.

Paolo


Reply via email to