1//! Macros for checking that types have the same layout as other types.
2
3#![allow(unused_macros)]
4
5/// Check that the size and alignment of a type match the `sys` bindings.
6macro_rules! check_type {
7 ($struct:ident) => {
8 assert_eq_size!($struct, c::$struct);
9 assert_eq_align!($struct, c::$struct);
10 };
11}
12
13/// The same as `check_type`, but for unions and anonymous structs we've
14/// renamed to avoid having types like `bindgen_ty_1` in the API.
15macro_rules! check_renamed_type {
16 ($to:ident, $from:ident) => {
17 assert_eq_size!($to, c::$from);
18 assert_eq_align!($to, c::$from);
19 };
20}
21
22/// Check that the field of a struct has the same offset as the corresponding
23/// field in the `sys` bindings.
24macro_rules! check_struct_field {
25 ($struct:ident, $field:ident) => {
26 const_assert_eq!(
27 memoffset::offset_of!($struct, $field),
28 memoffset::offset_of!(c::$struct, $field)
29 );
30
31 // This can't use `const_assert_eq` because `span_of` returns a
32 // `Range`, which can't be compared in const contexts.
33 assert_eq!(
34 memoffset::span_of!($struct, $field),
35 memoffset::span_of!(c::$struct, $field)
36 );
37 };
38}
39
40/// The same as `check_struct_field`, but for unions and anonymous structs
41/// we've renamed to avoid having types like `bindgen_ty_1` in the API.
42macro_rules! check_struct_renamed_field {
43 ($struct:ident, $to:ident, $from:ident) => {
44 const_assert_eq!(
45 memoffset::offset_of!($struct, $to),
46 memoffset::offset_of!(c::$struct, $from)
47 );
48
49 // As above, this can't use `const_assert_eq`.
50 assert_eq!(
51 memoffset::span_of!($struct, $to),
52 memoffset::span_of!(c::$struct, $from)
53 );
54 };
55}
56
57/// The same as `check_struct_renamed_field`, but for when both the struct and
58/// a field are renamed.
59macro_rules! check_renamed_struct_renamed_field {
60 ($to_struct:ident, $from_struct:ident, $to:ident, $from:ident) => {
61 const_assert_eq!(
62 memoffset::offset_of!($to_struct, $to),
63 memoffset::offset_of!(c::$from_struct, $from)
64 );
65
66 // As above, this can't use `const_assert_eq`.
67 assert_eq!(
68 memoffset::span_of!($to_struct, $to),
69 memoffset::span_of!(c::$from_struct, $from)
70 );
71 };
72}
73
74/// For the common case of no renaming, check all fields of a struct.
75macro_rules! check_struct {
76 ($name:ident, $($field:ident),*) => {
77 // Check the size and alignment.
78 check_type!($name);
79
80 // Check that we have all the fields.
81 if false {
82 #[allow(unreachable_code)]
83 let _test = $name {
84 $($field: panic!()),*
85 };
86 }
87
88 // Check that the fields have the right sizes and offsets.
89 $(check_struct_field!($name, $field));*
90 };
91}
92