Skip to content

Commit 8e3f9a8

Browse files
committed
Implement cli option for custom derive
closes #2170
1 parent a2fe04c commit 8e3f9a8

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed

bindgen-cli/options.rs

+48
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,24 @@ where
225225
"Create PartialEq implementation, if it can not be derived \
226226
automatically.",
227227
),
228+
Arg::new("with-derive-custom")
229+
.long("with-derive-custom")
230+
.help(
231+
"Derive custom traits on any type. \
232+
Don't use with --with-derive-custom-struct.",
233+
)
234+
.value_name("trait")
235+
.multiple_occurrences(true)
236+
.number_of_values(1),
237+
Arg::new("with-derive-custom-struct")
238+
.long("with-derive-custom-struct")
239+
.help(
240+
"Derive custom traits on any struct.\
241+
Don't use with --with-derive-custom.",
242+
)
243+
.value_name("trait")
244+
.multiple_occurrences(true)
245+
.number_of_values(1),
228246
Arg::new("with-derive-default")
229247
.long("with-derive-default")
230248
.help("Derive Default on any type."),
@@ -744,6 +762,36 @@ where
744762
builder = builder.impl_partialeq(true);
745763
}
746764

765+
if let Some(traits) = matches.values_of("with-derive-custom") {
766+
#[derive(Debug)]
767+
struct CustomTraitCallback {
768+
derives: Vec<String>
769+
}
770+
impl bindgen::callbacks::ParseCallbacks for CustomTraitCallback {
771+
fn add_derives(&self, _name: &str) -> Vec<String> {
772+
self.derives.to_owned()
773+
}
774+
}
775+
776+
let derives: Vec<String> = traits.into_iter().map(|t| t.to_string()).collect();
777+
builder = builder.parse_callbacks(Box::new(CustomTraitCallback { derives }));
778+
}
779+
780+
if let Some(traits) = matches.values_of("with-derive-custom-struct") {
781+
#[derive(Debug)]
782+
struct CustomTraitCallback {
783+
derives: Vec<String>
784+
}
785+
impl bindgen::callbacks::ParseCallbacks for CustomTraitCallback {
786+
fn add_derives_struct(&self, _name: &str) -> Vec<String> {
787+
self.derives.to_owned()
788+
}
789+
}
790+
791+
let derives: Vec<String> = traits.into_iter().map(|t| t.to_string()).collect();
792+
builder = builder.parse_callbacks(Box::new(CustomTraitCallback { derives }));
793+
}
794+
747795
if matches.is_present("with-derive-default") {
748796
builder = builder.derive_default(true);
749797
}

bindgen/callbacks.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! A public API for more fine-grained customization of bindgen behavior.
22
3+
34
pub use crate::ir::analysis::DeriveTrait;
45
pub use crate::ir::derive::CanDerive as ImplementsTrait;
56
pub use crate::ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue};
@@ -108,4 +109,12 @@ pub trait ParseCallbacks: fmt::Debug {
108109
fn add_derives(&self, _name: &str) -> Vec<String> {
109110
vec![]
110111
}
112+
113+
/// Provide a list of custom derive attributes.
114+
///
115+
/// If no additional attributes are wanted, this function should return an
116+
/// empty `Vec`.
117+
fn add_derives_struct(&self, _name: &str) -> Vec<String> {
118+
vec![]
119+
}
111120
}

bindgen/codegen/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -2113,10 +2113,17 @@ impl CodeGenerator for CompInfo {
21132113
// The custom derives callback may return a list of derive attributes;
21142114
// add them to the end of the list.
21152115
let custom_derives;
2116+
let custom_derives_struct;
21162117
if let Some(cb) = &ctx.options().parse_callbacks {
21172118
custom_derives = cb.add_derives(&canonical_name);
21182119
// In most cases this will be a no-op, since custom_derives will be empty.
21192120
derives.extend(custom_derives.iter().map(|s| s.as_str()));
2121+
2122+
custom_derives_struct = match self.kind() {
2123+
CompKind::Struct => cb.add_derives_struct(&canonical_name),
2124+
_ => vec![],
2125+
};
2126+
derives.extend(custom_derives_struct.iter().map(|s| s.as_str()));
21202127
};
21212128

21222129
if !derives.is_empty() {

0 commit comments

Comments
 (0)