rust: qemu-api-macros: add automatic TryFrom/TryInto derivation

This is going to be fairly common. Using a custom procedural macro
provides better error messages and automatically finds the right
type.

Note that this is different from the same-named macro in the
derive_more crate.  That one provides conversion from e.g. tuples
to enums with tuple variants, not from integers to enums.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2024-12-04 08:58:46 +01:00
parent a3b620fff7
commit 809c703a60
2 changed files with 73 additions and 29 deletions

View file

@ -45,7 +45,7 @@ pub const TYPE_PL011_LUMINARY: &::std::ffi::CStr = c_str!("pl011_luminary");
#[doc(alias = "offset")]
#[allow(non_camel_case_types)]
#[repr(u64)]
#[derive(Debug)]
#[derive(Debug, qemu_api_macros::TryInto)]
pub enum RegisterOffset {
/// Data Register
///
@ -102,32 +102,6 @@ pub enum RegisterOffset {
//Reserved = 0x04C,
}
impl core::convert::TryFrom<u64> for RegisterOffset {
type Error = u64;
fn try_from(value: u64) -> Result<Self, Self::Error> {
macro_rules! case {
($($discriminant:ident),*$(,)*) => {
/* check that matching on all macro arguments compiles, which means we are not
* missing any enum value; if the type definition ever changes this will stop
* compiling.
*/
const fn _assert_exhaustive(val: RegisterOffset) {
match val {
$(RegisterOffset::$discriminant => (),)*
}
}
match value {
$(x if x == Self::$discriminant as u64 => Ok(Self::$discriminant),)*
_ => Err(value),
}
}
}
case! { DR, RSR, FR, FBRD, ILPR, IBRD, LCR_H, CR, FLS, IMSC, RIS, MIS, ICR, DMACR }
}
}
pub mod registers {
//! Device registers exposed as typed structs which are backed by arbitrary
//! integer bitmaps. [`Data`], [`Control`], [`LineControl`], etc.