From: Paolo Bonzini Date: Tue, 13 May 2025 11:04:41 +0000 (+0200) Subject: rust: qemu-api-macros: add from_bits and into_bits to #[derive(TryInto)] X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=214518614c1ce7eb7a002452cd43a7597f90d543;p=thirdparty%2Fqemu.git 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 --- diff --git a/rust/qemu-api-macros/src/lib.rs b/rust/qemu-api-macros/src/lib.rs index ceb79f09f9..103470785e 100644 --- a/rust/qemu-api-macros/src/lib.rs +++ b/rust/qemu-api-macros/src/lib.rs @@ -192,24 +192,52 @@ fn get_variants(input: &DeriveInput) -> Result<&Punctuated, Macr Ok(&e.variants) } +#[rustfmt::skip::macros(quote)] +fn derive_tryinto_body( + name: &Ident, + variants: &Punctuated, + repr: &Path, +) -> Result { + 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 { let repr = get_repr_uN(&input, "#[derive(TryInto)]")?; - let name = &input.ident; - let variants = get_variants(&input)?; - let discriminants: Vec<&Ident> = variants.iter().map(|f| &f.ident).collect(); + 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 { - #(const #discriminants: #repr = #name::#discriminants as #repr;)*; - match value { - #(#discriminants => Ok(Self::#discriminants),)* - _ => Err(value), - } + #body } } })