Improves bindings for typed and anonymous enums

This commit is contained in:
Cameron Mulhern
2020-07-28 17:17:10 -04:00
committed by Emilio Cobos Álvarez
parent d537b6523f
commit d6a6580fc0
37 changed files with 147 additions and 82 deletions
+13 -1
View File
@@ -3,7 +3,6 @@
#![allow(non_upper_case_globals, dead_code)]
use crate::ir::context::BindgenContext;
use cexpr;
use clang_sys::*;
@@ -498,6 +497,19 @@ impl Cursor {
}
}
/// Get the boolean constant value for this cursor's enum variant referent.
///
/// Returns None if the cursor's referent is not an enum variant.
pub fn enum_val_boolean(&self) -> Option<bool> {
unsafe {
if self.kind() == CXCursor_EnumConstantDecl {
Some(clang_getEnumConstantDeclValue(self.x) != 0)
} else {
None
}
}
}
/// Get the signed constant value for this cursor's enum variant referent.
///
/// Returns None if the cursor's referent is not an enum variant.
+42 -12
View File
@@ -2438,6 +2438,7 @@ enum EnumBuilder<'a> {
is_bitfield: bool,
},
Consts {
repr: proc_macro2::TokenStream,
variants: Vec<proc_macro2::TokenStream>,
codegen_depth: usize,
},
@@ -2459,6 +2460,14 @@ impl<'a> EnumBuilder<'a> {
}
}
/// Returns true if the builder is for a rustified enum.
fn is_rust_enum(&self) -> bool {
match *self {
EnumBuilder::Rust { .. } => true,
_ => false,
}
}
/// Create a new enum given an item builder, a canonical name, a name for
/// the representation, and which variation it should be generated as.
fn new(
@@ -2467,6 +2476,7 @@ impl<'a> EnumBuilder<'a> {
repr: proc_macro2::TokenStream,
enum_variation: EnumVariation,
enum_codegen_depth: usize,
is_ty_named: bool,
) -> Self {
let ident = Ident::new(name, Span::call_site());
@@ -2492,13 +2502,22 @@ impl<'a> EnumBuilder<'a> {
}
}
EnumVariation::Consts => EnumBuilder::Consts {
variants: vec![quote! {
#( #attrs )*
pub type #ident = #repr;
}],
codegen_depth: enum_codegen_depth,
},
EnumVariation::Consts => {
let mut variants = Vec::new();
if is_ty_named {
variants.push(quote! {
#( #attrs )*
pub type #ident = #repr;
});
}
EnumBuilder::Consts {
repr: repr,
variants: variants,
codegen_depth: enum_codegen_depth,
}
}
EnumVariation::ModuleConsts => {
let ident = Ident::new(
@@ -2530,7 +2549,12 @@ impl<'a> EnumBuilder<'a> {
is_ty_named: bool,
) -> Self {
let variant_name = ctx.rust_mangle(variant.name());
let is_rust_enum = self.is_rust_enum();
let expr = match variant.val() {
EnumVariantValue::Boolean(v) if is_rust_enum => {
helpers::ast_ty::uint_expr(v as u64)
}
EnumVariantValue::Boolean(v) => quote!(#v),
EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v),
EnumVariantValue::Unsigned(v) => helpers::ast_ty::uint_expr(v),
};
@@ -2593,7 +2617,7 @@ impl<'a> EnumBuilder<'a> {
self
}
EnumBuilder::Consts { .. } => {
EnumBuilder::Consts { ref repr, .. } => {
let constant_name = match mangling_prefix {
Some(prefix) => {
Cow::Owned(format!("{}_{}", prefix, variant_name))
@@ -2601,10 +2625,12 @@ impl<'a> EnumBuilder<'a> {
None => variant_name,
};
let ty = if is_ty_named { &rust_ty } else { repr };
let ident = ctx.rust_ident(constant_name);
result.push(quote! {
#doc
pub const #ident : #rust_ty = #expr ;
pub const #ident : #ty = #expr ;
});
self
@@ -2859,9 +2885,12 @@ impl CodeGenerator for Enum {
});
}
let repr = {
let repr_name = ctx.rust_ident_raw(repr_name);
quote! { #repr_name }
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 mut builder = EnumBuilder::new(
@@ -2870,6 +2899,7 @@ impl CodeGenerator for Enum {
repr,
variation,
item.codegen_depth(ctx),
enum_ty.name().is_some(),
);
// A map where we keep a value -> variant relation.
+17 -10
View File
@@ -3,7 +3,7 @@
use super::super::codegen::EnumVariation;
use super::context::{BindgenContext, TypeId};
use super::item::Item;
use super::ty::TypeKind;
use super::ty::{Type, TypeKind};
use crate::clang;
use crate::ir::annotations::Annotations;
use crate::ir::item::ItemCanonicalPath;
@@ -69,15 +69,17 @@ impl Enum {
.and_then(|et| Item::from_ty(&et, declaration, None, ctx).ok());
let mut variants = vec![];
let variant_ty =
repr.and_then(|r| ctx.resolve_type(r).safe_canonical_type(ctx));
let is_bool = variant_ty.map_or(false, Type::is_bool);
// Assume signedness since the default type by the C standard is an int.
let is_signed = repr
.and_then(|r| ctx.resolve_type(r).safe_canonical_type(ctx))
.map_or(true, |ty| match *ty.kind() {
TypeKind::Int(ref int_kind) => int_kind.is_signed(),
ref other => {
panic!("Since when enums can be non-integers? {:?}", other)
}
});
let is_signed = variant_ty.map_or(true, |ty| match *ty.kind() {
TypeKind::Int(ref int_kind) => int_kind.is_signed(),
ref other => {
panic!("Since when enums can be non-integers? {:?}", other)
}
});
let type_name = ty.spelling();
let type_name = if type_name.is_empty() {
@@ -90,7 +92,9 @@ impl Enum {
let definition = declaration.definition().unwrap_or(declaration);
definition.visit(|cursor| {
if cursor.kind() == CXCursor_EnumConstantDecl {
let value = if is_signed {
let value = if is_bool {
cursor.enum_val_boolean().map(EnumVariantValue::Boolean)
} else if is_signed {
cursor.enum_val_signed().map(EnumVariantValue::Signed)
} else {
cursor.enum_val_unsigned().map(EnumVariantValue::Unsigned)
@@ -234,6 +238,9 @@ pub struct EnumVariant {
/// A constant value assigned to an enumeration variant.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum EnumVariantValue {
/// A boolean constant.
Boolean(bool),
/// A signed constant.
Signed(i64),
@@ -45,7 +45,7 @@ impl ::std::ops::BitAndAssign for Foo {
}
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Foo(pub i32);
pub struct Foo(pub ::std::os::raw::c_int);
impl Buz {
pub const Bar: Buz = Buz(2);
}
@@ -86,7 +86,7 @@ impl ::std::ops::BitAndAssign for Buz {
}
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Buz(pub i8);
pub struct Buz(pub ::std::os::raw::c_schar);
pub const NS_FOO: _bindgen_ty_1 = _bindgen_ty_1(1);
pub const NS_BAR: _bindgen_ty_1 = _bindgen_ty_1(2);
impl ::std::ops::BitOr<_bindgen_ty_1> for _bindgen_ty_1 {
@@ -117,7 +117,7 @@ impl ::std::ops::BitAndAssign for _bindgen_ty_1 {
}
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct _bindgen_ty_1(pub u32);
pub struct _bindgen_ty_1(pub ::std::os::raw::c_uint);
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct Dummy {
@@ -153,7 +153,7 @@ impl ::std::ops::BitAndAssign for Dummy__bindgen_ty_1 {
}
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Dummy__bindgen_ty_1(pub u32);
pub struct Dummy__bindgen_ty_1(pub ::std::os::raw::c_uint);
#[test]
fn bindgen_test_layout_Dummy() {
assert_eq!(
@@ -45,4 +45,4 @@ impl ::std::ops::BitAndAssign for Foo {
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Foo(pub i32);
pub struct Foo(pub ::std::os::raw::c_int);
@@ -45,4 +45,4 @@ impl ::std::ops::BitAndAssign for Foo {
}
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Foo(pub i32);
pub struct Foo(pub ::std::os::raw::c_int);
@@ -8,7 +8,7 @@
pub const foo_THIS: foo = 0;
pub const foo_SHOULD_BE: foo = 1;
pub const foo_A_CONSTANT: foo = 2;
pub type foo = u32;
pub type foo = ::std::os::raw::c_uint;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct bar {
@@ -6,7 +6,7 @@
)]
pub mod foo {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
pub const THIS: Type = 0;
pub const SHOULD_BE: Type = 1;
pub const A_CONSTANT: Type = 2;
@@ -16,7 +16,7 @@ pub mod root {
#[allow(unused_imports)]
use self::super::super::super::root;
pub mod foo {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
pub const THIS: Type = 0;
pub const SHOULD_BE: Type = 1;
pub const A_CONSTANT: Type = 2;
@@ -6,7 +6,7 @@
)]
pub mod foo {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
pub const Type: Type = 0;
pub const Type_: Type = 1;
pub const Type1: Type = 2;
@@ -6,7 +6,7 @@
)]
pub mod Foo {
pub type Type = i32;
pub type Type = ::std::os::raw::c_int;
pub const Variant1: Type = 0;
pub const Variant2: Type = 1;
pub const Variant3: Type = 2;
@@ -6,7 +6,7 @@
)]
pub mod one_Foo {
pub type Type = i32;
pub type Type = ::std::os::raw::c_int;
pub const Variant1: Type = 0;
pub const Variant2: Type = 1;
}
@@ -6,7 +6,7 @@
)]
pub mod foo {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
pub const THIS: Type = 0;
pub const SHOULD_BE: Type = 1;
pub const A_CONSTANT: Type = 2;
@@ -14,20 +14,20 @@ pub mod foo {
pub const AND_ALSO_THIS: Type = 42;
}
pub mod anon_enum {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
pub const Variant1: Type = 0;
pub const Variant2: Type = 1;
pub const Variant3: Type = 2;
}
pub mod ns1_foo {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
pub const THIS: Type = 0;
pub const SHOULD_BE: Type = 1;
pub const A_CONSTANT: Type = 2;
pub const ALSO_THIS: Type = 42;
}
pub mod ns2_Foo {
pub type Type = i32;
pub type Type = ::std::os::raw::c_int;
pub const Variant1: Type = 0;
pub const Variant2: Type = 1;
}
@@ -205,7 +205,7 @@ impl Default for Baz {
}
}
pub mod one_Foo {
pub type Type = i32;
pub type Type = ::std::os::raw::c_int;
pub const Variant1: Type = 0;
pub const Variant2: Type = 1;
}
@@ -6,7 +6,7 @@
)]
pub mod Foo {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
pub const bar: Type = 0;
pub const baz: Type = 1;
pub const blap: Type = 2;
+6 -6
View File
@@ -5,30 +5,30 @@
non_upper_case_globals
)]
pub type EmptyConstified = u32;
pub type EmptyConstified = ::std::os::raw::c_uint;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum EmptyRustified {
__bindgen_cannot_repr_c_on_empty_enum = 0,
}
pub mod EmptyModule {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
}
#[repr(i8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum EmptyClassRustified {
__bindgen_cannot_repr_c_on_empty_enum = 0,
}
pub type EmptyClassConstified = i8;
pub type EmptyClassConstified = ::std::os::raw::c_char;
pub mod EmptyClassModule {
pub type Type = i8;
pub type Type = ::std::os::raw::c_char;
}
#[repr(i8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ForwardClassRustified {
__bindgen_cannot_repr_c_on_empty_enum = 0,
}
pub type ForwardClassConstified = i8;
pub type ForwardClassConstified = ::std::os::raw::c_char;
pub mod ForwardClassModule {
pub type Type = i8;
pub type Type = ::std::os::raw::c_char;
}
@@ -39,9 +39,9 @@ impl ::std::ops::BitAndAssign for Foo {
}
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Foo(pub u32);
pub struct Foo(pub ::std::os::raw::c_uint);
pub mod Neg {
pub type Type = i32;
pub type Type = ::std::os::raw::c_int;
pub const MinusOne: Type = -1;
pub const One: Type = 1;
}
@@ -7,9 +7,9 @@
pub const Foo_Bar: Foo = 0;
pub const Foo_Qux: Foo = 1;
pub type Foo = u32;
pub type Foo = ::std::os::raw::c_uint;
pub mod Neg {
pub type Type = i32;
pub type Type = ::std::os::raw::c_int;
pub const MinusOne: Type = -1;
pub const One: Type = 1;
}
@@ -6,12 +6,12 @@
)]
pub mod Foo {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
pub const Bar: Type = 0;
pub const Qux: Type = 1;
}
pub mod Neg {
pub type Type = i32;
pub type Type = ::std::os::raw::c_int;
pub const MinusOne: Type = -1;
pub const One: Type = 1;
}
@@ -12,7 +12,7 @@ pub enum Foo {
Qux = 1,
}
pub mod Neg {
pub type Type = i32;
pub type Type = ::std::os::raw::c_int;
pub const MinusOne: Type = -1;
pub const One: Type = 1;
}
@@ -61,4 +61,4 @@ impl ::std::ops::BitAndAssign for B {
#[repr(transparent)]
/// Document enum
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct B(pub u32);
pub struct B(pub ::std::os::raw::c_uint);
+1 -1
View File
@@ -7,7 +7,7 @@
pub mod B {
/// Document enum
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
/// Document field with three slashes
pub const VAR_A: Type = 0;
/// Document field with preceeding star
+1 -1
View File
@@ -21,4 +21,4 @@ pub const B_VAR_E: B = 4;
/// Very interesting documentation, definitely.
pub const B_VAR_F: B = 5;
/// Document enum
pub type B = u32;
pub type B = ::std::os::raw::c_uint;
+1 -1
View File
@@ -13,4 +13,4 @@ pub enum Foo {
}
pub const Neg_MinusOne: Neg = -1;
pub const Neg_One: Neg = 1;
pub type Neg = i32;
pub type Neg = ::std::os::raw::c_int;
@@ -14,4 +14,4 @@ pub const OGRErr_PASS: OGRErr = 0;
/// Should see OGRERR_NONE instead of CUSTOM_OGRERR_NONE below.
pub const OGRErr_OGRERR_NONE: OGRErr = 1;
/// <div rustbindgen replaces="OGRErr"></div>
pub type OGRErr = u32;
pub type OGRErr = ::std::os::raw::c_uint;
@@ -43,3 +43,13 @@ pub enum MuchULongLong {
pub enum BoolEnumsAreFun {
Value = 1,
}
pub const AnonymousVariantOne: _bindgen_ty_1 =
_bindgen_ty_1::AnonymousVariantOne;
pub const AnonymousVariantTwo: _bindgen_ty_1 =
_bindgen_ty_1::AnonymousVariantTwo;
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
AnonymousVariantOne = 0,
AnonymousVariantTwo = 1,
}
@@ -7,18 +7,20 @@
pub const Foo_Bar: Foo = 0;
pub const Foo_Qux: Foo = 1;
pub type Foo = u8;
pub type Foo = ::std::os::raw::c_uchar;
pub const Neg_MinusOne: Neg = -1;
pub const Neg_One: Neg = 1;
pub type Neg = i8;
pub type Neg = ::std::os::raw::c_schar;
pub const Bigger_Much: Bigger = 255;
pub const Bigger_Larger: Bigger = 256;
pub type Bigger = u16;
pub type Bigger = ::std::os::raw::c_ushort;
pub const MuchLong_MuchLow: MuchLong = -4294967296;
pub type MuchLong = i64;
pub type MuchLong = ::std::os::raw::c_long;
pub const MuchLongLong_I64_MIN: MuchLongLong = -9223372036854775808;
pub type MuchLongLong = i64;
pub type MuchLongLong = ::std::os::raw::c_longlong;
pub const MuchULongLong_MuchHigh: MuchULongLong = 4294967296;
pub type MuchULongLong = u64;
pub const BoolEnumsAreFun_Value: BoolEnumsAreFun = 1;
pub type BoolEnumsAreFun = u8;
pub type MuchULongLong = ::std::os::raw::c_ulonglong;
pub const BoolEnumsAreFun_Value: BoolEnumsAreFun = true;
pub type BoolEnumsAreFun = bool;
pub const AnonymousVariantOne: ::std::os::raw::c_uchar = 0;
pub const AnonymousVariantTwo: ::std::os::raw::c_uchar = 1;
@@ -10,4 +10,3 @@
pub struct a {
pub _address: u8,
}
pub type a__bindgen_ty_1 = i32;
@@ -42,7 +42,7 @@ impl ::std::ops::BitAndAssign for MyDupeEnum {
}
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct MyDupeEnum(pub u32);
pub struct MyDupeEnum(pub ::std::os::raw::c_uint);
impl MyOtherDupeEnum {
pub const C: MyOtherDupeEnum = MyOtherDupeEnum(0);
}
@@ -80,4 +80,4 @@ impl ::std::ops::BitAndAssign for MyOtherDupeEnum {
}
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct MyOtherDupeEnum(pub u32);
pub struct MyOtherDupeEnum(pub ::std::os::raw::c_uint);
@@ -6,13 +6,13 @@
)]
pub mod MyDupeEnum {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
pub const A: Type = 0;
pub const A_alias: Type = 0;
pub const B: Type = 1;
}
pub mod MyOtherDupeEnum {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
pub const C: Type = 0;
pub const C_alias: Type = 0;
pub const D: Type = 1;
@@ -6,13 +6,13 @@
)]
pub mod MyDupeEnum {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
pub const A: Type = 0;
pub const A_alias: Type = 0;
pub const B: Type = 1;
}
pub mod MyOtherDupeEnum {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
pub const C: Type = 0;
pub const C_alias: Type = 0;
pub const D: Type = 1;
+1 -1
View File
@@ -14,7 +14,7 @@ pub mod root {
use self::super::super::root;
pub const AB_A: root::ns::AB = 0;
pub const AB_B: root::ns::AB = 1;
pub type AB = i32;
pub type AB = ::std::os::raw::c_int;
}
pub use self::super::root::ns::AB;
extern "C" {
@@ -7,12 +7,12 @@
pub const Foo_A: Foo = 0;
pub const Foo_B: Foo = 1;
pub type Foo = u32;
pub type Foo = ::std::os::raw::c_uint;
#[repr(transparent)]
#[derive(Debug, Copy, Clone)]
pub struct FooAlias(pub Foo);
pub mod Bar {
pub type Type = u32;
pub type Type = ::std::os::raw::c_uint;
pub const C: Type = 0;
pub const D: Type = 1;
}
@@ -30,7 +30,7 @@ pub enum Qux {
pub struct QuxAlias(pub Qux);
pub const Baz_G: Baz = 0;
pub const Baz_H: Baz = 1;
pub type Baz = u32;
pub type Baz = ::std::os::raw::c_uint;
#[repr(transparent)]
#[derive(Debug, Copy, Clone)]
pub struct BazAlias(pub Baz);
@@ -7,5 +7,5 @@
pub const a_b: a = 0;
pub const a_c: a = 1;
pub type a = u32;
pub type a = ::std::os::raw::c_uint;
pub type d = u32;
+1 -1
View File
@@ -19,4 +19,4 @@ impl Foo {
}
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Foo(pub i32);
pub struct Foo(pub ::std::os::raw::c_int);
@@ -7,4 +7,4 @@
pub const FOO_BAR: foo = 0;
pub const FOO_BAZ: foo = 1;
pub type foo = u32;
pub type foo = ::std::os::raw::c_uint;
+1 -1
View File
@@ -134,7 +134,7 @@ pub const StyleBar_Tag_Bar1: StyleBar_Tag = 0;
pub const StyleBar_Tag_Bar2: StyleBar_Tag = 0;
pub const StyleBar_Tag_Bar3: StyleBar_Tag = 0;
pub const StyleBar_Tag_Bar4: StyleBar_Tag = 0;
pub type StyleBar_Tag = i32;
pub type StyleBar_Tag = ::std::os::raw::c_int;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct StyleBar_StyleBar1_Body<T> {
+5
View File
@@ -30,3 +30,8 @@ enum MuchULongLong: unsigned long long {
enum BoolEnumsAreFun: bool {
Value = true,
};
enum : unsigned char {
AnonymousVariantOne,
AnonymousVariantTwo,
};