// Copyright 2024, Red Hat Inc. // Author(s): Paolo Bonzini // SPDX-License-Identifier: GPL-2.0-or-later #![doc(hidden)] //! This module provides macros to check the equality of types and //! the type of `struct` fields. This can be useful to ensure that //! types match the expectations of C code. //! //! Documentation is hidden because it only exposes macros, which //! are exported directly from `qemu_api`. // Based on https://stackoverflow.com/questions/64251852/x/70978292#70978292 // (stackoverflow answers are released under MIT license). #[doc(hidden)] pub trait EqType { type Itself; } impl EqType for T { type Itself = T; } /// Assert that two types are the same. /// /// # Examples /// /// ``` /// # use qemu_api::assert_same_type; /// # use std::ops::Deref; /// assert_same_type!(u32, u32); /// assert_same_type!( as Deref>::Target, u32); /// ``` /// /// Different types will cause a compile failure /// /// ```compile_fail /// # use qemu_api::assert_same_type; /// assert_same_type!(&Box, &u32); /// ``` #[macro_export] macro_rules! assert_same_type { ($t1:ty, $t2:ty) => { const _: () = { #[allow(unused)] fn assert_same_type(v: $t1) { fn types_must_be_equal(_: T) where T: $crate::assertions::EqType, { } types_must_be_equal::<_, $t2>(v); } }; }; } /// Assert that a field of a struct has the given type. /// /// # Examples /// /// ``` /// # use qemu_api::assert_field_type; /// pub struct A { /// field1: u32, /// } /// /// assert_field_type!(A, field1, u32); /// ``` /// /// Different types will cause a compile failure /// /// ```compile_fail /// # use qemu_api::assert_field_type; /// # pub struct A { field1: u32 } /// assert_field_type!(A, field1, i32); /// ``` #[macro_export] macro_rules! assert_field_type { ($t:ty, $i:tt, $ti:ty) => { const _: () = { #[allow(unused)] fn assert_field_type(v: $t) { fn types_must_be_equal(_: T) where T: $crate::assertions::EqType, { } types_must_be_equal::<_, $ti>(v.$i); } }; }; } /// Assert that an expression matches a pattern. This can also be /// useful to compare enums that do not implement `Eq`. /// /// # Examples /// /// ``` /// # use qemu_api::assert_match; /// // JoinHandle does not implement `Eq`, therefore the result /// // does not either. /// let result: Result, u32> = Err(42); /// assert_match!(result, Err(42)); /// ``` #[macro_export] macro_rules! assert_match { ($a:expr, $b:pat) => { assert!( match $a { $b => true, _ => false, }, "{} = {:?} does not match {}", stringify!($a), $a, stringify!($b) ); }; }