mirror of
https://gitee.com/openharmony/third_party_rust_bindgen
synced 2024-12-13 18:27:14 +00:00
Add option to translate enum integer types to native Rust integer types
Fixes #430
This commit is contained in:
parent
fb931bd6c1
commit
dedbea5bc0
@ -2524,7 +2524,7 @@ impl<'a> EnumBuilder<'a> {
|
||||
/// the representation, and which variation it should be generated as.
|
||||
fn new(
|
||||
name: &'a str,
|
||||
attrs: Vec<proc_macro2::TokenStream>,
|
||||
mut attrs: Vec<proc_macro2::TokenStream>,
|
||||
repr: proc_macro2::TokenStream,
|
||||
enum_variation: EnumVariation,
|
||||
enum_codegen_depth: usize,
|
||||
@ -2543,6 +2543,8 @@ impl<'a> EnumBuilder<'a> {
|
||||
},
|
||||
|
||||
EnumVariation::Rust { .. } => {
|
||||
// `repr` is guaranteed to be Rustified in Enum::codegen
|
||||
attrs.insert(0, quote! { #[repr( #repr )] });
|
||||
let tokens = quote!();
|
||||
EnumBuilder::Rust {
|
||||
codegen_depth: enum_codegen_depth + 1,
|
||||
@ -2820,51 +2822,73 @@ impl CodeGenerator for Enum {
|
||||
let ident = ctx.rust_ident(&name);
|
||||
let enum_ty = item.expect_type();
|
||||
let layout = enum_ty.layout(ctx);
|
||||
let variation = self.computed_enum_variation(ctx, item);
|
||||
|
||||
let repr = self.repr().map(|repr| ctx.resolve_type(repr));
|
||||
let repr = match repr {
|
||||
Some(repr) => match *repr.canonical_type(ctx).kind() {
|
||||
TypeKind::Int(int_kind) => int_kind,
|
||||
_ => panic!("Unexpected type as enum repr"),
|
||||
},
|
||||
None => {
|
||||
warn!(
|
||||
"Guessing type of enum! Forward declarations of enums \
|
||||
shouldn't be legal!"
|
||||
);
|
||||
IntKind::Int
|
||||
let repr_translated;
|
||||
let repr = match self.repr().map(|repr| ctx.resolve_type(repr)) {
|
||||
Some(repr)
|
||||
if !ctx.options().translate_enum_integer_types &&
|
||||
!variation.is_rust() =>
|
||||
{
|
||||
repr
|
||||
}
|
||||
};
|
||||
repr => {
|
||||
// An enum's integer type is translated to a native Rust
|
||||
// integer type in 3 cases:
|
||||
// * the enum is Rustified and we need a translated type for
|
||||
// the repr attribute
|
||||
// * the representation couldn't be determined from the C source
|
||||
// * it was explicitly requested as a bindgen option
|
||||
|
||||
let signed = repr.is_signed();
|
||||
let size = layout
|
||||
.map(|l| l.size)
|
||||
.or_else(|| repr.known_size())
|
||||
.unwrap_or(0);
|
||||
let kind = match repr {
|
||||
Some(repr) => match *repr.canonical_type(ctx).kind() {
|
||||
TypeKind::Int(int_kind) => int_kind,
|
||||
_ => panic!("Unexpected type as enum repr"),
|
||||
},
|
||||
None => {
|
||||
warn!(
|
||||
"Guessing type of enum! Forward declarations of enums \
|
||||
shouldn't be legal!"
|
||||
);
|
||||
IntKind::Int
|
||||
}
|
||||
};
|
||||
|
||||
let repr_name = match (signed, size) {
|
||||
(true, 1) => "i8",
|
||||
(false, 1) => "u8",
|
||||
(true, 2) => "i16",
|
||||
(false, 2) => "u16",
|
||||
(true, 4) => "i32",
|
||||
(false, 4) => "u32",
|
||||
(true, 8) => "i64",
|
||||
(false, 8) => "u64",
|
||||
_ => {
|
||||
warn!("invalid enum decl: signed: {}, size: {}", signed, size);
|
||||
"i32"
|
||||
let signed = kind.is_signed();
|
||||
let size = layout
|
||||
.map(|l| l.size)
|
||||
.or_else(|| kind.known_size())
|
||||
.unwrap_or(0);
|
||||
|
||||
let translated = match (signed, size) {
|
||||
(true, 1) => IntKind::I8,
|
||||
(false, 1) => IntKind::U8,
|
||||
(true, 2) => IntKind::I16,
|
||||
(false, 2) => IntKind::U16,
|
||||
(true, 4) => IntKind::I32,
|
||||
(false, 4) => IntKind::U32,
|
||||
(true, 8) => IntKind::I64,
|
||||
(false, 8) => IntKind::U64,
|
||||
_ => {
|
||||
warn!(
|
||||
"invalid enum decl: signed: {}, size: {}",
|
||||
signed, size
|
||||
);
|
||||
IntKind::I32
|
||||
}
|
||||
};
|
||||
|
||||
repr_translated =
|
||||
Type::new(None, None, TypeKind::Int(translated), false);
|
||||
&repr_translated
|
||||
}
|
||||
};
|
||||
|
||||
let mut attrs = vec![];
|
||||
|
||||
let variation = self.computed_enum_variation(ctx, item);
|
||||
|
||||
// TODO(emilio): Delegate this to the builders?
|
||||
match variation {
|
||||
EnumVariation::Rust { non_exhaustive } => {
|
||||
attrs.push(attributes::repr(repr_name));
|
||||
if non_exhaustive &&
|
||||
ctx.options().rust_features().non_exhaustive
|
||||
{
|
||||
@ -2934,13 +2958,7 @@ impl CodeGenerator for Enum {
|
||||
});
|
||||
}
|
||||
|
||||
let repr = match self.repr() {
|
||||
Some(ty) => ty.to_rust_ty_or_opaque(ctx, &()),
|
||||
None => {
|
||||
let repr_name = ctx.rust_ident_raw(repr_name);
|
||||
quote! { #repr_name }
|
||||
}
|
||||
};
|
||||
let repr = repr.to_rust_ty_or_opaque(ctx, item);
|
||||
|
||||
let mut builder = EnumBuilder::new(
|
||||
&name,
|
||||
|
18
src/lib.rs
18
src/lib.rs
@ -549,6 +549,10 @@ impl Builder {
|
||||
output_vector.push("--respect-cxx-access-specs".into());
|
||||
}
|
||||
|
||||
if self.options.translate_enum_integer_types {
|
||||
output_vector.push("--translate-enum-integer-types".into());
|
||||
}
|
||||
|
||||
// Add clang arguments
|
||||
|
||||
output_vector.push("--".into());
|
||||
@ -1568,6 +1572,16 @@ impl Builder {
|
||||
self.options.respect_cxx_access_specs = doit;
|
||||
self
|
||||
}
|
||||
|
||||
/// Always translate enum integer types to native Rust integer types.
|
||||
///
|
||||
/// This will result in enums having types such as `u32` and `i16` instead
|
||||
/// of `c_uint` and `c_short`. Types for Rustified enums are always
|
||||
/// translated.
|
||||
pub fn translate_enum_integer_types(mut self, doit: bool) -> Self {
|
||||
self.options.translate_enum_integer_types = doit;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration options for generated bindings.
|
||||
@ -1859,6 +1873,9 @@ struct BindgenOptions {
|
||||
/// Only make generated bindings `pub` if the items would be publically accessible
|
||||
/// by C++.
|
||||
respect_cxx_access_specs: bool,
|
||||
|
||||
/// Always translate enum integer types to native Rust integer types.
|
||||
translate_enum_integer_types: bool,
|
||||
}
|
||||
|
||||
/// TODO(emilio): This is sort of a lie (see the error message that results from
|
||||
@ -1996,6 +2013,7 @@ impl Default for BindgenOptions {
|
||||
wasm_import_module_name: None,
|
||||
dynamic_library_name: None,
|
||||
respect_cxx_access_specs: false,
|
||||
translate_enum_integer_types: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -503,6 +503,9 @@ where
|
||||
Arg::with_name("respect-cxx-access-specs")
|
||||
.long("respect-cxx-access-specs")
|
||||
.help("Makes generated bindings `pub` only for items if the items are publically accessible in C++."),
|
||||
Arg::with_name("translate-enum-integer-types")
|
||||
.long("translate-enum-integer-types")
|
||||
.help("Always translate enum integer types to native Rust integer types."),
|
||||
]) // .args()
|
||||
.get_matches_from(args);
|
||||
|
||||
@ -929,6 +932,10 @@ where
|
||||
builder = builder.respect_cxx_access_specs(true);
|
||||
}
|
||||
|
||||
if matches.is_present("translate-enum-integer-types") {
|
||||
builder = builder.translate_enum_integer_types(true);
|
||||
}
|
||||
|
||||
let verbose = matches.is_present("verbose");
|
||||
|
||||
Ok((builder, output, verbose))
|
||||
|
15
tests/expectations/tests/enum-translate-type.rs
Normal file
15
tests/expectations/tests/enum-translate-type.rs
Normal file
@ -0,0 +1,15 @@
|
||||
#![allow(
|
||||
dead_code,
|
||||
non_snake_case,
|
||||
non_camel_case_types,
|
||||
non_upper_case_globals
|
||||
)]
|
||||
|
||||
pub const my_enum1_A: my_enum1 = 0;
|
||||
pub type my_enum1 = u32;
|
||||
pub const my_enum2_B: my_enum2 = -1;
|
||||
pub type my_enum2 = i32;
|
||||
pub const my_enum3_C: my_enum3 = 0;
|
||||
pub type my_enum3 = i16;
|
||||
pub const my_enum4_D: my_enum4 = 255;
|
||||
pub type my_enum4 = u8;
|
14
tests/headers/enum-translate-type.hpp
Normal file
14
tests/headers/enum-translate-type.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
// bindgen-flags: --translate-enum-integer-types -- -std=c++11 -Wno-narrowing
|
||||
|
||||
enum my_enum1 {
|
||||
A = 0,
|
||||
};
|
||||
enum my_enum2 {
|
||||
B = -1,
|
||||
};
|
||||
enum my_enum3: short {
|
||||
C = 0,
|
||||
};
|
||||
enum my_enum4: unsigned char {
|
||||
D = -1,
|
||||
};
|
Loading…
Reference in New Issue
Block a user