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.
6 macro_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.
15 macro_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.
24 macro_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.
42 macro_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.
59 macro_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.
75 macro_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