1 // Copyright 2024, Red Hat Inc. 2 // Author(s): Paolo Bonzini <pbonzini@redhat.com> 3 // SPDX-License-Identifier: GPL-2.0-or-later 4 5 #![doc(hidden)] 6 //! This module provides macros to check the equality of types and 7 //! the type of `struct` fields. This can be useful to ensure that 8 //! types match the expectations of C code. 9 //! 10 //! Documentation is hidden because it only exposes macros, which 11 //! are exported directly from `qemu_api`. 12 13 // Based on https://stackoverflow.com/questions/64251852/x/70978292#70978292 14 // (stackoverflow answers are released under MIT license). 15 16 #[doc(hidden)] 17 pub trait EqType { 18 type Itself; 19 } 20 21 impl<T> EqType for T { 22 type Itself = T; 23 } 24 25 /// Assert that two types are the same. 26 /// 27 /// # Examples 28 /// 29 /// ``` 30 /// # use qemu_api::assert_same_type; 31 /// # use std::ops::Deref; 32 /// assert_same_type!(u32, u32); 33 /// assert_same_type!(<Box<u32> as Deref>::Target, u32); 34 /// ``` 35 /// 36 /// Different types will cause a compile failure 37 /// 38 /// ```compile_fail 39 /// # use qemu_api::assert_same_type; 40 /// assert_same_type!(&Box<u32>, &u32); 41 /// ``` 42 #[macro_export] 43 macro_rules! assert_same_type { 44 ($t1:ty, $t2:ty) => { 45 const _: () = { 46 #[allow(unused)] 47 fn assert_same_type(v: $t1) { 48 fn types_must_be_equal<T, U>(_: T) 49 where 50 T: $crate::assertions::EqType<Itself = U>, 51 { 52 } 53 types_must_be_equal::<_, $t2>(v); 54 } 55 }; 56 }; 57 } 58 59 /// Assert that a field of a struct has the given type. 60 /// 61 /// # Examples 62 /// 63 /// ``` 64 /// # use qemu_api::assert_field_type; 65 /// pub struct A { 66 /// field1: u32, 67 /// } 68 /// 69 /// assert_field_type!(A, field1, u32); 70 /// ``` 71 /// 72 /// Different types will cause a compile failure 73 /// 74 /// ```compile_fail 75 /// # use qemu_api::assert_field_type; 76 /// # pub struct A { field1: u32 } 77 /// assert_field_type!(A, field1, i32); 78 /// ``` 79 #[macro_export] 80 macro_rules! assert_field_type { 81 ($t:ty, $i:tt, $ti:ty) => { 82 const _: () = { 83 #[allow(unused)] 84 fn assert_field_type(v: $t) { 85 fn types_must_be_equal<T, U>(_: T) 86 where 87 T: $crate::assertions::EqType<Itself = U>, 88 { 89 } 90 types_must_be_equal::<_, $ti>(v.$i); 91 } 92 }; 93 }; 94 95 ($t:ty, $i:tt, $ti:ty, num = $num:ident) => { 96 const _: () = { 97 #[allow(unused)] 98 fn assert_field_type(v: $t) { 99 fn types_must_be_equal<T, U>(_: T) 100 where 101 T: $crate::assertions::EqType<Itself = U>, 102 { 103 } 104 let index: usize = v.$num.try_into().unwrap(); 105 types_must_be_equal::<_, &$ti>(&v.$i[index]); 106 } 107 }; 108 }; 109 } 110 111 /// Assert that an expression matches a pattern. This can also be 112 /// useful to compare enums that do not implement `Eq`. 113 /// 114 /// # Examples 115 /// 116 /// ``` 117 /// # use qemu_api::assert_match; 118 /// // JoinHandle does not implement `Eq`, therefore the result 119 /// // does not either. 120 /// let result: Result<std::thread::JoinHandle<()>, u32> = Err(42); 121 /// assert_match!(result, Err(42)); 122 /// ``` 123 #[macro_export] 124 macro_rules! assert_match { 125 ($a:expr, $b:pat) => { 126 assert!( 127 match $a { 128 $b => true, 129 _ => false, 130 }, 131 "{} = {:?} does not match {}", 132 stringify!($a), 133 $a, 134 stringify!($b) 135 ); 136 }; 137 } 138 139 /// Assert at compile time that an expression is true. This is similar 140 /// to `const { assert!(...); }` but it works outside functions, as well as 141 /// on versions of Rust before 1.79. 142 /// 143 /// # Examples 144 /// 145 /// ``` 146 /// # use qemu_api::static_assert; 147 /// static_assert!("abc".len() == 3); 148 /// ``` 149 /// 150 /// ```compile_fail 151 /// # use qemu_api::static_assert; 152 /// static_assert!("abc".len() == 2); // does not compile 153 /// ``` 154 #[macro_export] 155 macro_rules! static_assert { 156 ($x:expr) => { 157 const _: () = assert!($x); 158 }; 159 } 160