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