Skip to content

Commit 9c2167c

Browse files
committed
custom derives after DeriveInfo
1 parent a9d4198 commit 9c2167c

File tree

5 files changed

+74
-3
lines changed

5 files changed

+74
-3
lines changed

bindgen-cli/options.rs

+58
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,16 @@ where
204204
Arg::new("no-derive-copy")
205205
.long("no-derive-copy")
206206
.help("Avoid deriving Copy on any type."),
207+
Arg::new("with-derive-custom")
208+
.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")
215+
.multiple_occurrences(true)
216+
.number_of_values(1),
207217
Arg::new("no-derive-debug")
208218
.long("no-derive-debug")
209219
.help("Avoid deriving Debug on any type."),
@@ -1092,5 +1102,53 @@ where
10921102
builder = builder.wrap_unsafe_ops(true);
10931103
}
10941104

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![],
1134+
}
1135+
}
1136+
}
1137+
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 }));
1145+
}
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 }));
1151+
}
1152+
10951153
Ok((builder, output, verbose))
10961154
}

bindgen/callbacks.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
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;
45
pub use crate::ir::derive::CanDerive as ImplementsTrait;
56
pub use crate::ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue};
67
pub use crate::ir::int::IntKind;
@@ -120,10 +121,13 @@ pub trait ParseCallbacks: fmt::Debug {
120121

121122
/// Relevant information about a type to which new derive attributes will be added using
122123
/// [`ParseCallbacks::add_derives`].
124+
#[derive(Debug)]
123125
#[non_exhaustive]
124126
pub struct DeriveInfo<'a> {
125127
/// The name of the type.
126128
pub name: &'a str,
129+
/// The kind of the type
130+
pub kind: Option<CompKind>,
127131
}
128132

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

bindgen/codegen/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -2105,6 +2105,7 @@ impl CodeGenerator for CompInfo {
21052105
let custom_derives = ctx.options().all_callbacks(|cb| {
21062106
cb.add_derives(&crate::callbacks::DeriveInfo {
21072107
name: &canonical_name,
2108+
kind: Some(self.kind()),
21082109
})
21092110
});
21102111
// In most cases this will be a no-op, since custom_derives will be empty.
@@ -3121,7 +3122,10 @@ impl CodeGenerator for Enum {
31213122
// The custom derives callback may return a list of derive attributes;
31223123
// add them to the end of the list.
31233124
let custom_derives = ctx.options().all_callbacks(|cb| {
3124-
cb.add_derives(&crate::callbacks::DeriveInfo { name: &name })
3125+
cb.add_derives(&crate::callbacks::DeriveInfo {
3126+
name: &name,
3127+
kind: None,
3128+
})
31253129
});
31263130
// In most cases this will be a no-op, since custom_derives will be empty.
31273131
derives.extend(custom_derives.iter().map(|s| s.as_str()));

bindgen/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ mod clang;
6565
mod codegen;
6666
mod deps;
6767
mod features;
68-
mod ir;
68+
pub mod ir;
6969
mod parse;
7070
mod regex_set;
7171
mod time;
@@ -91,7 +91,7 @@ use crate::ir::context::{BindgenContext, ItemId};
9191
pub use crate::ir::function::Abi;
9292
use crate::ir::item::Item;
9393
use crate::parse::ParseError;
94-
use crate::regex_set::RegexSet;
94+
pub use crate::regex_set::RegexSet;
9595

9696
use std::borrow::Cow;
9797
use std::env;

bindgen/regex_set.rs

+5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ pub struct RegexSet {
1616
}
1717

1818
impl RegexSet {
19+
/// Create a new RegexSet
20+
pub fn new() -> RegexSet {
21+
RegexSet { ..Default::default() }
22+
}
23+
1924
/// Is this set empty?
2025
pub fn is_empty(&self) -> bool {
2126
self.items.is_empty()

0 commit comments

Comments
 (0)