mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-01 14:53:54 -06:00
rust: qemu-api-macros: add from_bits and into_bits to #[derive(TryInto)]
These const functions make it possible to use enums easily together with the bitfield-struct crate. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
9c8ff2a1ed
commit
214518614c
1 changed files with 38 additions and 10 deletions
|
@ -193,23 +193,51 @@ fn get_variants(input: &DeriveInput) -> Result<&Punctuated<Variant, Comma>, Macr
|
|||
}
|
||||
|
||||
#[rustfmt::skip::macros(quote)]
|
||||
fn derive_tryinto_or_error(input: DeriveInput) -> Result<proc_macro2::TokenStream, MacroError> {
|
||||
let repr = get_repr_uN(&input, "#[derive(TryInto)]")?;
|
||||
|
||||
let name = &input.ident;
|
||||
let variants = get_variants(&input)?;
|
||||
fn derive_tryinto_body(
|
||||
name: &Ident,
|
||||
variants: &Punctuated<Variant, Comma>,
|
||||
repr: &Path,
|
||||
) -> Result<proc_macro2::TokenStream, MacroError> {
|
||||
let discriminants: Vec<&Ident> = variants.iter().map(|f| &f.ident).collect();
|
||||
|
||||
Ok(quote! {
|
||||
#(const #discriminants: #repr = #name::#discriminants as #repr;)*;
|
||||
match value {
|
||||
#(#discriminants => Ok(#name::#discriminants),)*
|
||||
_ => Err(value),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[rustfmt::skip::macros(quote)]
|
||||
fn derive_tryinto_or_error(input: DeriveInput) -> Result<proc_macro2::TokenStream, MacroError> {
|
||||
let repr = get_repr_uN(&input, "#[derive(TryInto)]")?;
|
||||
let name = &input.ident;
|
||||
let body = derive_tryinto_body(name, get_variants(&input)?, &repr)?;
|
||||
let errmsg = format!("invalid value for {name}");
|
||||
|
||||
Ok(quote! {
|
||||
impl #name {
|
||||
#[allow(dead_code)]
|
||||
pub const fn into_bits(self) -> #repr {
|
||||
self as #repr
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const fn from_bits(value: #repr) -> Self {
|
||||
match ({
|
||||
#body
|
||||
}) {
|
||||
Ok(x) => x,
|
||||
Err(_) => panic!(#errmsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl core::convert::TryFrom<#repr> for #name {
|
||||
type Error = #repr;
|
||||
|
||||
fn try_from(value: #repr) -> Result<Self, Self::Error> {
|
||||
#(const #discriminants: #repr = #name::#discriminants as #repr;)*;
|
||||
match value {
|
||||
#(#discriminants => Ok(Self::#discriminants),)*
|
||||
_ => Err(value),
|
||||
}
|
||||
#body
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue