xref: /qemu/rust/qemu-api/src/assertions.rs (revision 7f65d4e58b67d6e5ee05c9381a50ef1eba3a5a1e)
1*7f65d4e5SPaolo Bonzini // Copyright 2024, Red Hat Inc.
2*7f65d4e5SPaolo Bonzini // Author(s): Paolo Bonzini <pbonzini@redhat.com>
3*7f65d4e5SPaolo Bonzini // SPDX-License-Identifier: GPL-2.0-or-later
4*7f65d4e5SPaolo Bonzini 
5*7f65d4e5SPaolo Bonzini //! This module provides macros to check the equality of types and
6*7f65d4e5SPaolo Bonzini //! the type of `struct` fields.  This can be useful to ensure that
7*7f65d4e5SPaolo Bonzini //! types match the expectations of C code.
8*7f65d4e5SPaolo Bonzini 
9*7f65d4e5SPaolo Bonzini // Based on https://stackoverflow.com/questions/64251852/x/70978292#70978292
10*7f65d4e5SPaolo Bonzini // (stackoverflow answers are released under MIT license).
11*7f65d4e5SPaolo Bonzini 
12*7f65d4e5SPaolo Bonzini #[doc(hidden)]
13*7f65d4e5SPaolo Bonzini pub trait EqType {
14*7f65d4e5SPaolo Bonzini     type Itself;
15*7f65d4e5SPaolo Bonzini }
16*7f65d4e5SPaolo Bonzini 
17*7f65d4e5SPaolo Bonzini impl<T> EqType for T {
18*7f65d4e5SPaolo Bonzini     type Itself = T;
19*7f65d4e5SPaolo Bonzini }
20*7f65d4e5SPaolo Bonzini 
21*7f65d4e5SPaolo Bonzini /// Assert that two types are the same.
22*7f65d4e5SPaolo Bonzini ///
23*7f65d4e5SPaolo Bonzini /// # Examples
24*7f65d4e5SPaolo Bonzini ///
25*7f65d4e5SPaolo Bonzini /// ```
26*7f65d4e5SPaolo Bonzini /// # use qemu_api::assert_same_type;
27*7f65d4e5SPaolo Bonzini /// # use std::ops::Deref;
28*7f65d4e5SPaolo Bonzini /// assert_same_type!(u32, u32);
29*7f65d4e5SPaolo Bonzini /// assert_same_type!(<Box<u32> as Deref>::Target, u32);
30*7f65d4e5SPaolo Bonzini /// ```
31*7f65d4e5SPaolo Bonzini ///
32*7f65d4e5SPaolo Bonzini /// Different types will cause a compile failure
33*7f65d4e5SPaolo Bonzini ///
34*7f65d4e5SPaolo Bonzini /// ```compile_fail
35*7f65d4e5SPaolo Bonzini /// # use qemu_api::assert_same_type;
36*7f65d4e5SPaolo Bonzini /// assert_same_type!(&Box<u32>, &u32);
37*7f65d4e5SPaolo Bonzini /// ```
38*7f65d4e5SPaolo Bonzini #[macro_export]
39*7f65d4e5SPaolo Bonzini macro_rules! assert_same_type {
40*7f65d4e5SPaolo Bonzini     ($t1:ty, $t2:ty) => {
41*7f65d4e5SPaolo Bonzini         const _: () = {
42*7f65d4e5SPaolo Bonzini             #[allow(unused)]
43*7f65d4e5SPaolo Bonzini             fn assert_same_type(v: $t1) {
44*7f65d4e5SPaolo Bonzini                 fn types_must_be_equal<T, U>(_: T)
45*7f65d4e5SPaolo Bonzini                 where
46*7f65d4e5SPaolo Bonzini                     T: $crate::assertions::EqType<Itself = U>,
47*7f65d4e5SPaolo Bonzini                 {
48*7f65d4e5SPaolo Bonzini                 }
49*7f65d4e5SPaolo Bonzini                 types_must_be_equal::<_, $t2>(v);
50*7f65d4e5SPaolo Bonzini             }
51*7f65d4e5SPaolo Bonzini         };
52*7f65d4e5SPaolo Bonzini     };
53*7f65d4e5SPaolo Bonzini }
54*7f65d4e5SPaolo Bonzini 
55*7f65d4e5SPaolo Bonzini /// Assert that a field of a struct has the given type.
56*7f65d4e5SPaolo Bonzini ///
57*7f65d4e5SPaolo Bonzini /// # Examples
58*7f65d4e5SPaolo Bonzini ///
59*7f65d4e5SPaolo Bonzini /// ```
60*7f65d4e5SPaolo Bonzini /// # use qemu_api::assert_field_type;
61*7f65d4e5SPaolo Bonzini /// pub struct A {
62*7f65d4e5SPaolo Bonzini ///     field1: u32,
63*7f65d4e5SPaolo Bonzini /// }
64*7f65d4e5SPaolo Bonzini ///
65*7f65d4e5SPaolo Bonzini /// assert_field_type!(A, field1, u32);
66*7f65d4e5SPaolo Bonzini /// ```
67*7f65d4e5SPaolo Bonzini ///
68*7f65d4e5SPaolo Bonzini /// Different types will cause a compile failure
69*7f65d4e5SPaolo Bonzini ///
70*7f65d4e5SPaolo Bonzini /// ```compile_fail
71*7f65d4e5SPaolo Bonzini /// # use qemu_api::assert_field_type;
72*7f65d4e5SPaolo Bonzini /// # pub struct A { field1: u32 }
73*7f65d4e5SPaolo Bonzini /// assert_field_type!(A, field1, i32);
74*7f65d4e5SPaolo Bonzini /// ```
75*7f65d4e5SPaolo Bonzini #[macro_export]
76*7f65d4e5SPaolo Bonzini macro_rules! assert_field_type {
77*7f65d4e5SPaolo Bonzini     ($t:ty, $i:tt, $ti:ty) => {
78*7f65d4e5SPaolo Bonzini         const _: () = {
79*7f65d4e5SPaolo Bonzini             #[allow(unused)]
80*7f65d4e5SPaolo Bonzini             fn assert_field_type(v: $t) {
81*7f65d4e5SPaolo Bonzini                 fn types_must_be_equal<T, U>(_: T)
82*7f65d4e5SPaolo Bonzini                 where
83*7f65d4e5SPaolo Bonzini                     T: $crate::assertions::EqType<Itself = U>,
84*7f65d4e5SPaolo Bonzini                 {
85*7f65d4e5SPaolo Bonzini                 }
86*7f65d4e5SPaolo Bonzini                 types_must_be_equal::<_, $ti>(v.$i);
87*7f65d4e5SPaolo Bonzini             }
88*7f65d4e5SPaolo Bonzini         };
89*7f65d4e5SPaolo Bonzini     };
90*7f65d4e5SPaolo Bonzini }
91