diff options
author | Porter Smith <flowbish@gmail.com> | 2018-11-28 14:45:08 -0800 |
---|---|---|
committer | Porter Smith <flowbish@gmail.com> | 2018-11-28 15:07:27 -0800 |
commit | 94698e02a6c346ed20a2bf6d4217be9e308ddb15 (patch) | |
tree | 9f073ccdb84e0735758e1fdd47155e417cb0aaa7 | |
parent | adfc52a02c8d53878a6d9c19373cc4470e423aeb (diff) |
Add source annotation to express explicit derives for a type.
This allows for explicit selection of which traits are derived for a
type, e.g. deriving custom traits on particular types that need it.
Example usage:
```C++
/// <div rustbindgen derive="Clone"></div>
/// <div rustbindgen derive="MyDerivableTrait"></div>
struct foo { ... };
```
generates into
```Rust
#[derive(Clone,MyDerivableTrait)]
struct foo { ... }
```
-rw-r--r-- | src/codegen/mod.rs | 2 | ||||
-rw-r--r-- | src/ir/annotations.rs | 11 | ||||
-rw-r--r-- | tests/expectations/tests/derive-custom.rs | 97 | ||||
-rw-r--r-- | tests/headers/derive-custom.h | 28 |
4 files changed, 138 insertions, 0 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 073745b1..9405f11b 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1764,6 +1764,8 @@ impl CodeGenerator for CompInfo { derives.push("Eq"); } + derives.extend(item.annotations().derives().iter().map(String::as_str)); + if !derives.is_empty() { attributes.push(attributes::derives(&derives)) } diff --git a/src/ir/annotations.rs b/src/ir/annotations.rs index bc57b555..654e1686 100644 --- a/src/ir/annotations.rs +++ b/src/ir/annotations.rs @@ -58,6 +58,8 @@ pub struct Annotations { /// In that case, bindgen will generate a constant for `Bar` instead of /// `Baz`. constify_enum_variant: bool, + /// List of explicit derives for this type. + derives: Vec<String>, } fn parse_accessor(s: &str) -> FieldAccessorKind { @@ -79,6 +81,7 @@ impl Default for Annotations { private_fields: None, accessor_kind: None, constify_enum_variant: false, + derives: vec![], } } } @@ -130,6 +133,11 @@ impl Annotations { self.use_instead_of.as_ref().map(|s| &**s) } + /// The list of derives that have been specified in this annotation. + pub fn derives(&self) -> &[String] { + &self.derives + } + /// Should we avoid implementing the `Copy` trait? pub fn disallow_copy(&self) -> bool { self.disallow_copy @@ -165,6 +173,9 @@ impl Annotations { attr.value.split("::").map(Into::into).collect(), ) } + "derive" => { + self.derives.push(attr.value) + } "private" => { self.private_fields = Some(attr.value != "false") } diff --git a/tests/expectations/tests/derive-custom.rs b/tests/expectations/tests/derive-custom.rs new file mode 100644 index 00000000..1184e435 --- /dev/null +++ b/tests/expectations/tests/derive-custom.rs @@ -0,0 +1,97 @@ +/* automatically generated by rust-bindgen */ + +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +/// <div rustbindgen derive="Debug"></div> +#[repr(C)] +#[derive(Default, Debug)] +pub struct my_type { + pub a: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_my_type() { + assert_eq!( + ::std::mem::size_of::<my_type>(), + 4usize, + concat!("Size of: ", stringify!(my_type)) + ); + assert_eq!( + ::std::mem::align_of::<my_type>(), + 4usize, + concat!("Alignment of ", stringify!(my_type)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<my_type>())).a as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(my_type), + "::", + stringify!(a) + ) + ); +} +/// <div rustbindgen derive="Debug"></div> +/// <div rustbindgen derive="Clone"></div> +#[repr(C)] +#[derive(Default, Debug, Clone)] +pub struct my_type2 { + pub a: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_my_type2() { + assert_eq!( + ::std::mem::size_of::<my_type2>(), + 4usize, + concat!("Size of: ", stringify!(my_type2)) + ); + assert_eq!( + ::std::mem::align_of::<my_type2>(), + 4usize, + concat!("Alignment of ", stringify!(my_type2)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<my_type2>())).a as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(my_type2), + "::", + stringify!(a) + ) + ); +} +/// <div rustbindgen derive="Debug" derive="Clone"></div> +#[repr(C)] +#[derive(Default, Debug, Clone)] +pub struct my_type3 { + pub a: ::std::os::raw::c_ulong, +} +#[test] +fn bindgen_test_layout_my_type3() { + assert_eq!( + ::std::mem::size_of::<my_type3>(), + 8usize, + concat!("Size of: ", stringify!(my_type3)) + ); + assert_eq!( + ::std::mem::align_of::<my_type3>(), + 8usize, + concat!("Alignment of ", stringify!(my_type3)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<my_type3>())).a as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(my_type3), + "::", + stringify!(a) + ) + ); +} diff --git a/tests/headers/derive-custom.h b/tests/headers/derive-custom.h new file mode 100644 index 00000000..83f2ce08 --- /dev/null +++ b/tests/headers/derive-custom.h @@ -0,0 +1,28 @@ +// bindgen-flags: --no-derive-debug --no-derive-copy --default-enum-style rust + +/** <div rustbindgen derive="Debug"></div> */ +struct my_type; + +/** <div rustbindgen derive="Clone"></div> */ +struct my_type; + +struct my_type { + int a; +}; + +/** + * <div rustbindgen derive="Debug"></div> + * <div rustbindgen derive="Clone"></div> + */ +struct my_type2; + +struct my_type2 { + unsigned a; +}; + +/** + * <div rustbindgen derive="Debug" derive="Clone"></div> + */ +struct my_type3 { + unsigned long a; +}; |