Skip to content

Commit 25db012

Browse files
committed
Introduce TypeKind instead of CompKind
1 parent 9c2167c commit 25db012

File tree

3 files changed

+98
-56
lines changed

3 files changed

+98
-56
lines changed

bindgen-cli/options.rs

+73-48
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
use bindgen::callbacks::TypeKind;
12
use bindgen::{
23
builder, AliasVariation, Builder, CodegenConfig, EnumVariation,
3-
MacroTypeVariation, NonCopyUnionStyle, RustTarget,
4+
MacroTypeVariation, NonCopyUnionStyle, RegexSet, RustTarget,
45
DEFAULT_ANON_FIELDS_PREFIX, RUST_TARGET_STRINGS,
56
};
67
use clap::{App, Arg};
@@ -206,12 +207,26 @@ where
206207
.help("Avoid deriving Copy on any type."),
207208
Arg::new("with-derive-custom")
208209
.long("with-derive-custom")
209-
.help(
210-
"Derive custom traits on any kind of type. \
211-
The derive value must be of the shape <regex>=<kind>=<derive> where <kind> can be one of: \
212-
Any, Struct, or Union.",
213-
)
214-
.value_name("trait")
210+
.help( "Derive custom traits on any type whose name matches <regex>. The <derives> value must be of the shape <regex>=<traits> where <derives> is a comma-separated list of traits.")
211+
.value_name("derives")
212+
.multiple_occurrences(true)
213+
.number_of_values(1),
214+
Arg::new("with-derive-custom-struct")
215+
.long("with-derive-custom-struct")
216+
.help( "Derive custom traits on any `struct` whose name matches <regex>. The <derives> value must be of the shape <regex>=<traits> where <derives> is a comma-separated list of traits.")
217+
.value_name("derives")
218+
.multiple_occurrences(true)
219+
.number_of_values(1),
220+
Arg::new("with-derive-custom-enum")
221+
.long("with-derive-custom-enum")
222+
.help( "Derive custom traits on any `enum` whose name matches <regex>. The <derives> value must be of the shape <regex>=<traits> where <derives> is a comma-separated list of traits.")
223+
.value_name("derives")
224+
.multiple_occurrences(true)
225+
.number_of_values(1),
226+
Arg::new("with-derive-custom-union")
227+
.long("with-derive-custom-union")
228+
.help( "Derive custom traits on any `union` whose name matches <regex>. The <derives> value must be of the shape <regex>=<traits> where <derives> is a comma-separated list of traits.")
229+
.value_name("derives")
215230
.multiple_occurrences(true)
216231
.number_of_values(1),
217232
Arg::new("no-derive-debug")
@@ -1102,52 +1117,62 @@ where
11021117
builder = builder.wrap_unsafe_ops(true);
11031118
}
11041119

1105-
if let Some(custom_derives) = matches.values_of("with-derive-custom") {
1106-
#[derive(Debug)]
1107-
struct CustomDeriveCallback {
1108-
derive: String,
1109-
kind: String,
1110-
regex: String,
1111-
}
1112-
impl bindgen::callbacks::ParseCallbacks for CustomDeriveCallback {
1113-
fn add_derives(&self, info: &bindgen::callbacks::DeriveInfo<'_>) -> Vec<String> {
1114-
match self.kind.to_lowercase().as_str() {
1115-
"struct" => match info.kind {
1116-
Some(bindgen::ir::comp::CompKind::Struct) => {}, // continue
1117-
_ => return vec![], // bail
1118-
}
1119-
"union" => match info.kind {
1120-
Some(bindgen::ir::comp::CompKind::Union) => {}, // continue
1121-
_ => return vec![], // bail
1122-
}
1123-
"any" => {} // continue
1124-
other => panic!("Invalid custom derive: Unexpected kind '{}'", other)
1125-
}
1126-
1127-
let mut re = bindgen::RegexSet::new();
1128-
re.insert(self.regex.to_owned());
1129-
re.build(false);
1130-
1131-
match re.matches(info.name) {
1132-
true => vec![self.derive.to_owned()],
1133-
false => vec![],
1120+
#[derive(Debug)]
1121+
struct CustomDeriveCallback {
1122+
derives: Vec<String>,
1123+
kind: Option<TypeKind>,
1124+
regex_set: bindgen::RegexSet,
1125+
}
1126+
1127+
impl bindgen::callbacks::ParseCallbacks for CustomDeriveCallback {
1128+
fn add_derives(
1129+
&self,
1130+
info: &bindgen::callbacks::DeriveInfo<'_>,
1131+
) -> Vec<String> {
1132+
if self.kind.map(|kind| kind == info.kind).unwrap_or(true) {
1133+
if self.regex_set.matches(info.name) {
1134+
return self.derives.clone();
11341135
}
11351136
}
1137+
vec![]
11361138
}
1139+
}
11371140

1138-
for custom_derive in custom_derives {
1139-
let mut values = custom_derive.rsplitn(3, "=");
1140-
let derive = values.next().expect("Invalid custom derive: Expected 3 parts, found 0").to_owned();
1141-
let kind = values.next().expect("Invalid custom derive: Expected 3 parts, found 1").to_owned();
1142-
let regex = values.next().expect("Invalid custom derive: Expected 3 parts, found 2").to_owned();
1143-
1144-
builder = builder.parse_callbacks(Box::new(CustomDeriveCallback { derive, kind, regex: regex }));
1141+
for (values, kind) in [
1142+
(matches.values_of("with-derive-custom"), None),
1143+
(
1144+
matches.values_of("with-derive-custom-struct"),
1145+
Some(TypeKind::Struct),
1146+
),
1147+
(
1148+
matches.values_of("with-derive-custom-enum"),
1149+
Some(TypeKind::Enum),
1150+
),
1151+
(
1152+
matches.values_of("with-derive-custom-union"),
1153+
Some(TypeKind::Union),
1154+
),
1155+
] {
1156+
if let Some(custom_derives) = values {
1157+
for custom_derive in custom_derives {
1158+
let (regex, derives) = custom_derive
1159+
.rsplit_once("=")
1160+
.expect("Invalid custom derive argument: Missing `=`");
1161+
let derives =
1162+
derives.split(",").map(|s| s.to_owned()).collect();
1163+
1164+
let mut regex_set = RegexSet::new();
1165+
regex_set.insert(regex);
1166+
regex_set.build(false);
1167+
1168+
builder =
1169+
builder.parse_callbacks(Box::new(CustomDeriveCallback {
1170+
derives,
1171+
kind,
1172+
regex_set,
1173+
}));
1174+
}
11451175
}
1146-
1147-
1148-
1149-
// let derives: Vec<String> = traits.into_iter().map(|t| t.to_string()).collect();
1150-
// builder = builder.parse_callbacks(Box::new(CustomTraitCallback { derives }));
11511176
}
11521177

11531178
Ok((builder, output, verbose))

bindgen/callbacks.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! A public API for more fine-grained customization of bindgen behavior.
22
33
pub use crate::ir::analysis::DeriveTrait;
4-
use crate::ir::comp::CompKind;
54
pub use crate::ir::derive::CanDerive as ImplementsTrait;
65
pub use crate::ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue};
76
pub use crate::ir::int::IntKind;
@@ -126,8 +125,19 @@ pub trait ParseCallbacks: fmt::Debug {
126125
pub struct DeriveInfo<'a> {
127126
/// The name of the type.
128127
pub name: &'a str,
129-
/// The kind of the type
130-
pub kind: Option<CompKind>,
128+
/// The kind of the type.
129+
pub kind: TypeKind,
130+
}
131+
132+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
133+
/// The kind of the current type.
134+
pub enum TypeKind {
135+
/// The type is a Rust `struct`.
136+
Struct,
137+
/// The type is a Rust `enum`.
138+
Enum,
139+
/// The type is a Rust `union`.
140+
Union,
131141
}
132142

133143
/// An struct providing information about the item being passed to `ParseCallbacks::generated_name_override`.

bindgen/codegen/mod.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use self::struct_layout::StructLayoutTracker;
1818

1919
use super::BindgenOptions;
2020

21+
use crate::callbacks::{DeriveInfo, TypeKind as DeriveTypeKind};
2122
use crate::ir::analysis::{HasVtable, Sizedness};
2223
use crate::ir::annotations::FieldAccessorKind;
2324
use crate::ir::comp::{
@@ -2100,12 +2101,18 @@ impl CodeGenerator for CompInfo {
21002101
let mut derives: Vec<_> = derivable_traits.into();
21012102
derives.extend(item.annotations().derives().iter().map(String::as_str));
21022103

2104+
let is_rust_union = is_union && struct_layout.is_rust_union();
2105+
21032106
// The custom derives callback may return a list of derive attributes;
21042107
// add them to the end of the list.
21052108
let custom_derives = ctx.options().all_callbacks(|cb| {
2106-
cb.add_derives(&crate::callbacks::DeriveInfo {
2109+
cb.add_derives(&DeriveInfo {
21072110
name: &canonical_name,
2108-
kind: Some(self.kind()),
2111+
kind: if is_rust_union {
2112+
DeriveTypeKind::Union
2113+
} else {
2114+
DeriveTypeKind::Struct
2115+
},
21092116
})
21102117
});
21112118
// In most cases this will be a no-op, since custom_derives will be empty.
@@ -2119,7 +2126,7 @@ impl CodeGenerator for CompInfo {
21192126
attributes.push(attributes::must_use());
21202127
}
21212128

2122-
let mut tokens = if is_union && struct_layout.is_rust_union() {
2129+
let mut tokens = if is_rust_union {
21232130
quote! {
21242131
#( #attributes )*
21252132
pub union #canonical_ident
@@ -3122,9 +3129,9 @@ impl CodeGenerator for Enum {
31223129
// The custom derives callback may return a list of derive attributes;
31233130
// add them to the end of the list.
31243131
let custom_derives = ctx.options().all_callbacks(|cb| {
3125-
cb.add_derives(&crate::callbacks::DeriveInfo {
3132+
cb.add_derives(&DeriveInfo {
31263133
name: &name,
3127-
kind: None,
3134+
kind: DeriveTypeKind::Enum,
31283135
})
31293136
});
31303137
// In most cases this will be a no-op, since custom_derives will be empty.

0 commit comments

Comments
 (0)