mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 01:33:56 -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)]
|
#[rustfmt::skip::macros(quote)]
|
||||||
fn derive_tryinto_or_error(input: DeriveInput) -> Result<proc_macro2::TokenStream, MacroError> {
|
fn derive_tryinto_body(
|
||||||
let repr = get_repr_uN(&input, "#[derive(TryInto)]")?;
|
name: &Ident,
|
||||||
|
variants: &Punctuated<Variant, Comma>,
|
||||||
let name = &input.ident;
|
repr: &Path,
|
||||||
let variants = get_variants(&input)?;
|
) -> Result<proc_macro2::TokenStream, MacroError> {
|
||||||
let discriminants: Vec<&Ident> = variants.iter().map(|f| &f.ident).collect();
|
let discriminants: Vec<&Ident> = variants.iter().map(|f| &f.ident).collect();
|
||||||
|
|
||||||
Ok(quote! {
|
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 {
|
impl core::convert::TryFrom<#repr> for #name {
|
||||||
type Error = #repr;
|
type Error = #repr;
|
||||||
|
|
||||||
fn try_from(value: #repr) -> Result<Self, Self::Error> {
|
fn try_from(value: #repr) -> Result<Self, Self::Error> {
|
||||||
#(const #discriminants: #repr = #name::#discriminants as #repr;)*;
|
#body
|
||||||
match value {
|
|
||||||
#(#discriminants => Ok(Self::#discriminants),)*
|
|
||||||
_ => Err(value),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue