diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2024-12-11 12:18:06 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2025-01-10 23:34:43 +0100 |
commit | 7f65d4e58b67d6e5ee05c9381a50ef1eba3a5a1e (patch) | |
tree | c95e80c41e4eb93b73f17236a9d1022008476e50 /rust/qemu-api/src/assertions.rs | |
parent | ca0d60a6ad777ab617cbc4e6f328eaff60617b3f (diff) | |
download | qemu-7f65d4e58b67d6e5ee05c9381a50ef1eba3a5a1e.zip qemu-7f65d4e58b67d6e5ee05c9381a50ef1eba3a5a1e.tar.gz qemu-7f65d4e58b67d6e5ee05c9381a50ef1eba3a5a1e.tar.bz2 |
rust: add a utility module for compile-time type checks
It is relatively common in the low-level qemu_api code to assert that
a field of a struct has a specific type; for example, it can be used
to ensure that the fields match what the qemu_api and C code expects
for safety.
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'rust/qemu-api/src/assertions.rs')
-rw-r--r-- | rust/qemu-api/src/assertions.rs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/rust/qemu-api/src/assertions.rs b/rust/qemu-api/src/assertions.rs new file mode 100644 index 0000000..6e42046 --- /dev/null +++ b/rust/qemu-api/src/assertions.rs @@ -0,0 +1,90 @@ +// Copyright 2024, Red Hat Inc. +// Author(s): Paolo Bonzini <pbonzini@redhat.com> +// SPDX-License-Identifier: GPL-2.0-or-later + +//! 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. + +// 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<T> 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!(<Box<u32> as Deref>::Target, u32); +/// ``` +/// +/// Different types will cause a compile failure +/// +/// ```compile_fail +/// # use qemu_api::assert_same_type; +/// assert_same_type!(&Box<u32>, &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, U>(_: T) + where + T: $crate::assertions::EqType<Itself = U>, + { + } + 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, U>(_: T) + where + T: $crate::assertions::EqType<Itself = U>, + { + } + types_must_be_equal::<_, $ti>(v.$i); + } + }; + }; +} |