diff options
Diffstat (limited to 'rust/qemu-macros/src/lib.rs')
-rw-r--r-- | rust/qemu-macros/src/lib.rs | 97 |
1 files changed, 96 insertions, 1 deletions
diff --git a/rust/qemu-macros/src/lib.rs b/rust/qemu-macros/src/lib.rs index 3e21b67..50239f2 100644 --- a/rust/qemu-macros/src/lib.rs +++ b/rust/qemu-macros/src/lib.rs @@ -13,9 +13,13 @@ use syn::{ Attribute, Data, DeriveInput, Error, Field, Fields, FieldsUnnamed, Ident, Meta, Path, Token, Variant, }; + mod bits; use bits::BitsConstInternal; +mod migration_state; +use migration_state::MigrationStateDerive; + #[cfg(test)] mod tests; @@ -401,7 +405,98 @@ pub fn bits_const_internal(ts: TokenStream) -> TokenStream { let ts = proc_macro2::TokenStream::from(ts); let mut it = ts.into_iter(); - BitsConstInternal::parse(&mut it) + let out = BitsConstInternal::parse(&mut it).unwrap_or_else(syn::Error::into_compile_error); + + // https://github.com/rust-lang/rust-clippy/issues/15852 + quote! { + { + #[allow(clippy::double_parens)] + #out + } + } + .into() +} + +/// Derive macro for generating migration state structures and trait +/// implementations. +/// +/// This macro generates a migration state struct and implements the +/// `ToMigrationState` trait for the annotated struct, enabling state +/// serialization and restoration. Note that defining a `VMStateDescription` +/// for the migration state struct is left to the user. +/// +/// # Container attributes +/// +/// The following attributes can be applied to the struct: +/// +/// - `#[migration_state(rename = CustomName)]` - Customizes the name of the +/// generated migration struct. By default, the generated struct is named +/// `{OriginalName}Migration`. +/// +/// # Field attributes +/// +/// The following attributes can be applied to individual fields: +/// +/// - `#[migration_state(omit)]` - Excludes the field from the migration state +/// entirely. +/// +/// - `#[migration_state(into(Type))]` - Converts the field using `.into()` +/// during both serialization and restoration. +/// +/// - `#[migration_state(try_into(Type))]` - Converts the field using +/// `.try_into()` during both serialization and restoration. Returns +/// `InvalidError` on conversion failure. +/// +/// - `#[migration_state(clone)]` - Clones the field value. +/// +/// 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`. +/// +/// # Examples +/// +/// Basic usage: +/// ```ignore +/// #[derive(ToMigrationState)] +/// struct MyStruct { +/// field1: u32, +/// field2: Timer, +/// } +/// ``` +/// +/// With attributes: +/// ```ignore +/// #[derive(ToMigrationState)] +/// #[migration_state(rename = CustomMigration)] +/// struct MyStruct { +/// #[migration_state(omit)] +/// runtime_field: u32, +/// +/// #[migration_state(clone)] +/// shared_data: String, +/// +/// #[migration_state(into(Cow<'static, str>), clone)] +/// converted_field: String, +/// +/// #[migration_state(try_into(i8))] +/// fallible_field: u32, +/// +/// // Default: use ToMigrationState trait recursively +/// nested_field: NestedStruct, +/// +/// // Primitive types have a default implementation of ToMigrationState +/// simple_field: u32, +/// } +/// ``` +#[proc_macro_derive(ToMigrationState, attributes(migration_state))] +pub fn derive_to_migration_state(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + MigrationStateDerive::expand(input) .unwrap_or_else(syn::Error::into_compile_error) .into() } |