mirror of
https://gitee.com/openharmony/third_party_rust_bindgen
synced 2024-12-13 18:27:14 +00:00
Add --no-default <regex> flag
Sometimes, we need customize the implement of `Default` for certain types, In these cases, the `nodefault` annotation can be used to prevent bindgen to autoderive the `Default` traits for a type.
This commit is contained in:
parent
30fb4eccb3
commit
d8082613e2
@ -18,6 +18,7 @@
|
||||
- [Replacing One Type with Another](./replacing-types.md)
|
||||
- [Preventing the Derivation of `Copy` and `Clone`](./nocopy.md)
|
||||
- [Preventing the Derivation of `Debug`](./nodebug.md)
|
||||
- [Preventing the Derivation of `Default`](./nodefault.md)
|
||||
- [Generating Bindings to C++](./cpp.md)
|
||||
- [Generating Bindings to Objective-c](./objc.md)
|
||||
- [Using Unions](./using-unions.md)
|
||||
|
48
book/src/nodefault.md
Normal file
48
book/src/nodefault.md
Normal file
@ -0,0 +1,48 @@
|
||||
# Preventing the Derivation of `Default`
|
||||
|
||||
`bindgen` will attempt to derive/impl the `Default` traits on a best-effort basis.
|
||||
Sometimes, we need customize the implement of `Default` for certain types,
|
||||
In these cases, the `nodefault` annotation can be used to prevent bindgen
|
||||
to autoderive the `Default` traits for a type.
|
||||
|
||||
### Library
|
||||
|
||||
* [`bindgen::Builder::no_default`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.no_default)
|
||||
|
||||
### Command Line
|
||||
|
||||
* `--no-default <regex>`
|
||||
|
||||
### Annotations
|
||||
|
||||
```c
|
||||
/**
|
||||
* We need to specify some preset values as the Default of Header.
|
||||
*
|
||||
* for example:
|
||||
*
|
||||
* <div rustbindgen nodefault></div>
|
||||
*/
|
||||
struct Header {
|
||||
unsigned int magic;
|
||||
unsigned char data[252];
|
||||
};
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
### Customize Implements
|
||||
|
||||
```rust,ignore
|
||||
// Include the generated bindings.
|
||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||
|
||||
impl Default for Header {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
magic: 0x10203040u32,
|
||||
data: [0; 252usize],
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
@ -118,7 +118,7 @@ fn derives_of_item(item: &Item, ctx: &BindgenContext) -> DerivableTraits {
|
||||
derivable_traits |= DerivableTraits::DEBUG;
|
||||
}
|
||||
|
||||
if item.can_derive_default(ctx) {
|
||||
if item.can_derive_default(ctx) && !item.annotations().disallow_default() {
|
||||
derivable_traits |= DerivableTraits::DEFAULT;
|
||||
}
|
||||
|
||||
@ -1900,8 +1900,10 @@ impl CodeGenerator for CompInfo {
|
||||
}
|
||||
|
||||
if !derivable_traits.contains(DerivableTraits::DEFAULT) {
|
||||
needs_default_impl =
|
||||
ctx.options().derive_default && !self.is_forward_declaration();
|
||||
needs_default_impl = ctx.options().derive_default &&
|
||||
!self.is_forward_declaration() &&
|
||||
!ctx.no_default_by_name(item) &&
|
||||
!item.annotations().disallow_default();
|
||||
}
|
||||
|
||||
let all_template_params = item.all_template_params(ctx);
|
||||
|
@ -446,11 +446,11 @@ impl DeriveTrait {
|
||||
match self {
|
||||
DeriveTrait::Copy => ctx.no_copy_by_name(item),
|
||||
DeriveTrait::Debug => ctx.no_debug_by_name(item),
|
||||
DeriveTrait::Default => ctx.no_default_by_name(item),
|
||||
DeriveTrait::Hash => ctx.no_hash_by_name(item),
|
||||
DeriveTrait::PartialEqOrPartialOrd => {
|
||||
ctx.no_partialeq_by_name(item)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,8 @@ pub struct Annotations {
|
||||
disallow_copy: bool,
|
||||
/// Manually disable deriving debug on this type.
|
||||
disallow_debug: bool,
|
||||
/// Manually disable deriving/implement default on this type.
|
||||
disallow_default: bool,
|
||||
/// Whether fields should be marked as private or not. You can set this on
|
||||
/// structs (it will apply to all the fields), or individual fields.
|
||||
private_fields: Option<bool>,
|
||||
@ -81,6 +83,7 @@ impl Default for Annotations {
|
||||
use_instead_of: None,
|
||||
disallow_copy: false,
|
||||
disallow_debug: false,
|
||||
disallow_default: false,
|
||||
private_fields: None,
|
||||
accessor_kind: None,
|
||||
constify_enum_variant: false,
|
||||
@ -155,6 +158,11 @@ impl Annotations {
|
||||
self.disallow_debug
|
||||
}
|
||||
|
||||
/// Should we avoid implementing the `Default` trait?
|
||||
pub fn disallow_default(&self) -> bool {
|
||||
self.disallow_default
|
||||
}
|
||||
|
||||
/// Should the fields be private?
|
||||
pub fn private_fields(&self) -> Option<bool> {
|
||||
self.private_fields
|
||||
@ -181,6 +189,7 @@ impl Annotations {
|
||||
"hide" => self.hide = true,
|
||||
"nocopy" => self.disallow_copy = true,
|
||||
"nodebug" => self.disallow_debug = true,
|
||||
"nodefault" => self.disallow_default = true,
|
||||
"replaces" => {
|
||||
self.use_instead_of = Some(
|
||||
attr.value.split("::").map(Into::into).collect(),
|
||||
|
@ -2591,6 +2591,12 @@ If you encounter an error missing from this list, please file an issue or a PR!"
|
||||
self.options().no_debug_types.matches(&name)
|
||||
}
|
||||
|
||||
/// Check if `--no-default` flag is enabled for this item.
|
||||
pub fn no_default_by_name(&self, item: &Item) -> bool {
|
||||
let name = item.path_for_whitelisting(self)[1..].join("::");
|
||||
self.options().no_default_types.matches(&name)
|
||||
}
|
||||
|
||||
/// Check if `--no-hash` flag is enabled for this item.
|
||||
pub fn no_hash_by_name(&self, item: &Item) -> bool {
|
||||
let name = item.path_for_whitelisting(self)[1..].join("::");
|
||||
|
13
src/lib.rs
13
src/lib.rs
@ -298,6 +298,7 @@ impl Builder {
|
||||
(&self.options.no_partialeq_types, "--no-partialeq"),
|
||||
(&self.options.no_copy_types, "--no-copy"),
|
||||
(&self.options.no_debug_types, "--no-debug"),
|
||||
(&self.options.no_default_types, "--no-default"),
|
||||
(&self.options.no_hash_types, "--no-hash"),
|
||||
];
|
||||
|
||||
@ -1446,6 +1447,13 @@ impl Builder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Don't derive/impl `Default` for a given type. Regular
|
||||
/// expressions are supported.
|
||||
pub fn no_default<T: Into<String>>(mut self, arg: T) -> Self {
|
||||
self.options.no_default_types.insert(arg.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Don't derive `Hash` for a given type. Regular
|
||||
/// expressions are supported.
|
||||
pub fn no_hash<T: Into<String>>(mut self, arg: T) -> Builder {
|
||||
@ -1745,6 +1753,9 @@ struct BindgenOptions {
|
||||
/// The set of types that we should not derive `Debug` for.
|
||||
no_debug_types: RegexSet,
|
||||
|
||||
/// The set of types that we should not derive/impl `Default` for.
|
||||
no_default_types: RegexSet,
|
||||
|
||||
/// The set of types that we should not derive `Hash` for.
|
||||
no_hash_types: RegexSet,
|
||||
|
||||
@ -1786,6 +1797,7 @@ impl BindgenOptions {
|
||||
&mut self.no_partialeq_types,
|
||||
&mut self.no_copy_types,
|
||||
&mut self.no_debug_types,
|
||||
&mut self.no_default_types,
|
||||
&mut self.no_hash_types,
|
||||
];
|
||||
let record_matches = self.record_matches;
|
||||
@ -1886,6 +1898,7 @@ impl Default for BindgenOptions {
|
||||
no_partialeq_types: Default::default(),
|
||||
no_copy_types: Default::default(),
|
||||
no_debug_types: Default::default(),
|
||||
no_default_types: Default::default(),
|
||||
no_hash_types: Default::default(),
|
||||
array_pointers_in_arguments: false,
|
||||
wasm_import_module_name: None,
|
||||
|
@ -451,6 +451,13 @@ where
|
||||
.takes_value(true)
|
||||
.multiple(true)
|
||||
.number_of_values(1),
|
||||
Arg::with_name("no-default")
|
||||
.long("no-default")
|
||||
.help("Avoid deriving/implement Default for types matching <regex>.")
|
||||
.value_name("regex")
|
||||
.takes_value(true)
|
||||
.multiple(true)
|
||||
.number_of_values(1),
|
||||
Arg::with_name("no-hash")
|
||||
.long("no-hash")
|
||||
.help("Avoid deriving Hash for types matching <regex>.")
|
||||
@ -871,6 +878,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(no_default) = matches.values_of("no-default") {
|
||||
for regex in no_default {
|
||||
builder = builder.no_default(regex);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(no_hash) = matches.values_of("no-hash") {
|
||||
for regex in no_hash {
|
||||
builder = builder.no_hash(regex);
|
||||
|
23
tests/expectations/tests/no_default.rs
Normal file
23
tests/expectations/tests/no_default.rs
Normal file
@ -0,0 +1,23 @@
|
||||
#![allow(
|
||||
dead_code,
|
||||
non_snake_case,
|
||||
non_camel_case_types,
|
||||
non_upper_case_globals
|
||||
)]
|
||||
|
||||
/// <div rustbindgen nodefault></div>
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct DefaultButWait {
|
||||
pub whatever: ::std::os::raw::c_int,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct DefaultButWaitDerived {
|
||||
pub whatever: DefaultButWait,
|
||||
}
|
||||
impl Default for DefaultButWaitDerived {
|
||||
fn default() -> Self {
|
||||
unsafe { ::std::mem::zeroed() }
|
||||
}
|
||||
}
|
22
tests/expectations/tests/no_default_bypass_derive_default.rs
Normal file
22
tests/expectations/tests/no_default_bypass_derive_default.rs
Normal file
@ -0,0 +1,22 @@
|
||||
#![allow(
|
||||
dead_code,
|
||||
non_snake_case,
|
||||
non_camel_case_types,
|
||||
non_upper_case_globals
|
||||
)]
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Generic<T> {
|
||||
pub t: [T; 40usize],
|
||||
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
|
||||
}
|
||||
impl<T> Default for Generic<T> {
|
||||
fn default() -> Self {
|
||||
unsafe { ::std::mem::zeroed() }
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct NoDefault<T> {
|
||||
pub t: [T; 40usize],
|
||||
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
|
||||
}
|
26
tests/expectations/tests/no_default_opaque.rs
Normal file
26
tests/expectations/tests/no_default_opaque.rs
Normal file
@ -0,0 +1,26 @@
|
||||
#![allow(
|
||||
dead_code,
|
||||
non_snake_case,
|
||||
non_camel_case_types,
|
||||
non_upper_case_globals
|
||||
)]
|
||||
|
||||
#[repr(C)]
|
||||
#[repr(align(4))]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct NoDefault {
|
||||
pub _bindgen_opaque_blob: u32,
|
||||
}
|
||||
#[test]
|
||||
fn bindgen_test_layout_NoDefault() {
|
||||
assert_eq!(
|
||||
::std::mem::size_of::<NoDefault>(),
|
||||
4usize,
|
||||
concat!("Size of: ", stringify!(NoDefault))
|
||||
);
|
||||
assert_eq!(
|
||||
::std::mem::align_of::<NoDefault>(),
|
||||
4usize,
|
||||
concat!("Alignment of ", stringify!(NoDefault))
|
||||
);
|
||||
}
|
35
tests/expectations/tests/no_default_whitelisted.rs
Normal file
35
tests/expectations/tests/no_default_whitelisted.rs
Normal file
@ -0,0 +1,35 @@
|
||||
#![allow(
|
||||
dead_code,
|
||||
non_snake_case,
|
||||
non_camel_case_types,
|
||||
non_upper_case_globals
|
||||
)]
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct NoDefault {
|
||||
pub i: ::std::os::raw::c_int,
|
||||
}
|
||||
#[test]
|
||||
fn bindgen_test_layout_NoDefault() {
|
||||
assert_eq!(
|
||||
::std::mem::size_of::<NoDefault>(),
|
||||
4usize,
|
||||
concat!("Size of: ", stringify!(NoDefault))
|
||||
);
|
||||
assert_eq!(
|
||||
::std::mem::align_of::<NoDefault>(),
|
||||
4usize,
|
||||
concat!("Alignment of ", stringify!(NoDefault))
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { &(*(::std::ptr::null::<NoDefault>())).i as *const _ as usize },
|
||||
0usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(NoDefault),
|
||||
"::",
|
||||
stringify!(i)
|
||||
)
|
||||
);
|
||||
}
|
11
tests/headers/no_default.hpp
Normal file
11
tests/headers/no_default.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
/** <div rustbindgen nodefault></div> */
|
||||
template<typename T>
|
||||
class DefaultButWait {
|
||||
int whatever;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class DefaultButWaitDerived {
|
||||
DefaultButWait<T> whatever;
|
||||
};
|
11
tests/headers/no_default_bypass_derive_default.hpp
Normal file
11
tests/headers/no_default_bypass_derive_default.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
// bindgen-flags: --no-default "NoDefault"
|
||||
|
||||
template<typename T>
|
||||
class Generic {
|
||||
T t[40];
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class NoDefault {
|
||||
T t[40];
|
||||
};
|
5
tests/headers/no_default_opaque.hpp
Normal file
5
tests/headers/no_default_opaque.hpp
Normal file
@ -0,0 +1,5 @@
|
||||
// bindgen-flags: --opaque-type "NoDefault" --no-default "NoDefault"
|
||||
|
||||
class NoDefault {
|
||||
int i;
|
||||
};
|
5
tests/headers/no_default_whitelisted.hpp
Normal file
5
tests/headers/no_default_whitelisted.hpp
Normal file
@ -0,0 +1,5 @@
|
||||
// bindgen-flags: --whitelist-type "NoDefault" --no-default "NoDefault"
|
||||
|
||||
class NoDefault {
|
||||
int i;
|
||||
};
|
Loading…
Reference in New Issue
Block a user