Skip to content

Commit 61636e9

Browse files
pvdrzkulp
authored andcommitted
add --newtype-global-enum option
1 parent 8b29355 commit 61636e9

File tree

6 files changed

+118
-18
lines changed

6 files changed

+118
-18
lines changed

src/codegen/mod.rs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2577,6 +2577,8 @@ pub enum EnumVariation {
25772577
NewType {
25782578
/// Indicates whether the newtype will have bitwise operators
25792579
is_bitfield: bool,
2580+
/// Indicates whether the variants will be represented as global constants
2581+
is_global: bool,
25802582
},
25812583
/// The code for this enum will use consts
25822584
Consts,
@@ -2614,16 +2616,26 @@ impl std::str::FromStr for EnumVariation {
26142616
"rust_non_exhaustive" => Ok(EnumVariation::Rust {
26152617
non_exhaustive: true,
26162618
}),
2617-
"bitfield" => Ok(EnumVariation::NewType { is_bitfield: true }),
2619+
"bitfield" => Ok(EnumVariation::NewType {
2620+
is_bitfield: true,
2621+
is_global: false,
2622+
}),
26182623
"consts" => Ok(EnumVariation::Consts),
26192624
"moduleconsts" => Ok(EnumVariation::ModuleConsts),
2620-
"newtype" => Ok(EnumVariation::NewType { is_bitfield: false }),
2625+
"newtype" => Ok(EnumVariation::NewType {
2626+
is_bitfield: false,
2627+
is_global: false,
2628+
}),
2629+
"newtype_global" => Ok(EnumVariation::NewType {
2630+
is_bitfield: false,
2631+
is_global: true,
2632+
}),
26212633
_ => Err(std::io::Error::new(
26222634
std::io::ErrorKind::InvalidInput,
26232635
concat!(
26242636
"Got an invalid EnumVariation. Accepted values ",
26252637
"are 'rust', 'rust_non_exhaustive', 'bitfield', 'consts',",
2626-
"'moduleconsts', and 'newtype'."
2638+
"'moduleconsts', 'newtype' and 'newtype_global'."
26272639
),
26282640
)),
26292641
}
@@ -2644,6 +2656,7 @@ enum EnumBuilder<'a> {
26442656
canonical_name: &'a str,
26452657
tokens: proc_macro2::TokenStream,
26462658
is_bitfield: bool,
2659+
is_global: bool,
26472660
},
26482661
Consts {
26492662
variants: Vec<proc_macro2::TokenStream>,
@@ -2684,14 +2697,18 @@ impl<'a> EnumBuilder<'a> {
26842697
let ident = Ident::new(name, Span::call_site());
26852698

26862699
match enum_variation {
2687-
EnumVariation::NewType { is_bitfield } => EnumBuilder::NewType {
2700+
EnumVariation::NewType {
2701+
is_bitfield,
2702+
is_global,
2703+
} => EnumBuilder::NewType {
26882704
codegen_depth: enum_codegen_depth,
26892705
canonical_name: name,
26902706
tokens: quote! {
26912707
#( #attrs )*
26922708
pub struct #ident (pub #repr);
26932709
},
26942710
is_bitfield,
2711+
is_global,
26952712
},
26962713

26972714
EnumVariation::Rust { .. } => {
@@ -2792,17 +2809,29 @@ impl<'a> EnumBuilder<'a> {
27922809
}
27932810
}
27942811

2795-
EnumBuilder::NewType { canonical_name, .. } => {
2812+
EnumBuilder::NewType {
2813+
canonical_name,
2814+
is_global,
2815+
..
2816+
} => {
27962817
if ctx.options().rust_features().associated_const && is_ty_named
27972818
{
27982819
let enum_ident = ctx.rust_ident(canonical_name);
27992820
let variant_ident = ctx.rust_ident(variant_name);
2800-
result.push(quote! {
2801-
impl #enum_ident {
2802-
#doc
2803-
pub const #variant_ident : #rust_ty = #rust_ty ( #expr );
2804-
}
2805-
});
2821+
let tokens = quote! {
2822+
#doc
2823+
pub const #variant_ident : #rust_ty = #rust_ty ( #expr );
2824+
};
2825+
2826+
if is_global {
2827+
result.push(tokens);
2828+
} else {
2829+
result.push(quote! {
2830+
impl #enum_ident {
2831+
#tokens
2832+
}
2833+
});
2834+
}
28062835
} else {
28072836
let ident = ctx.rust_ident(match mangling_prefix {
28082837
Some(prefix) => {

src/ir/enum_ty.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,25 @@ impl Enum {
187187
&ctx.options().bitfield_enums,
188188
item,
189189
) {
190-
EnumVariation::NewType { is_bitfield: true }
190+
EnumVariation::NewType {
191+
is_bitfield: true,
192+
is_global: false,
193+
}
191194
} else if self.is_matching_enum(ctx, &ctx.options().newtype_enums, item)
192195
{
193-
EnumVariation::NewType { is_bitfield: false }
196+
EnumVariation::NewType {
197+
is_bitfield: false,
198+
is_global: false,
199+
}
200+
} else if self.is_matching_enum(
201+
ctx,
202+
&ctx.options().newtype_global_enums,
203+
item,
204+
) {
205+
EnumVariation::NewType {
206+
is_bitfield: false,
207+
is_global: true,
208+
}
194209
} else if self.is_matching_enum(
195210
ctx,
196211
&ctx.options().rustified_enums,

src/lib.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,11 +279,19 @@ impl Builder {
279279
codegen::EnumVariation::Rust {
280280
non_exhaustive: true,
281281
} => "rust_non_exhaustive",
282-
codegen::EnumVariation::NewType { is_bitfield: true } => {
283-
"bitfield"
284-
}
285-
codegen::EnumVariation::NewType { is_bitfield: false } => {
286-
"newtype"
282+
codegen::EnumVariation::NewType {
283+
is_bitfield: true,
284+
..
285+
} => "bitfield",
286+
codegen::EnumVariation::NewType {
287+
is_bitfield: false,
288+
is_global,
289+
} => {
290+
if is_global {
291+
"newtype_global"
292+
} else {
293+
"newtype"
294+
}
287295
}
288296
codegen::EnumVariation::Consts => "consts",
289297
codegen::EnumVariation::ModuleConsts => "moduleconsts",
@@ -984,6 +992,18 @@ impl Builder {
984992
self
985993
}
986994

995+
/// Mark the given enum (or set of enums, if using a pattern) as a newtype
996+
/// whose variants are exposed as global constants.
997+
///
998+
/// Regular expressions are supported.
999+
///
1000+
/// This makes bindgen generate a type that isn't a Rust `enum`. Regular
1001+
/// expressions are supported.
1002+
pub fn newtype_global_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
1003+
self.options.newtype_global_enums.insert(arg);
1004+
self
1005+
}
1006+
9871007
/// Mark the given enum (or set of enums, if using a pattern) as a Rust
9881008
/// enum.
9891009
///
@@ -1759,6 +1779,9 @@ struct BindgenOptions {
17591779
/// The enum patterns to mark an enum as a newtype.
17601780
newtype_enums: RegexSet,
17611781

1782+
/// The enum patterns to mark an enum as a global newtype.
1783+
newtype_global_enums: RegexSet,
1784+
17621785
/// The enum patterns to mark an enum as a Rust enum.
17631786
rustified_enums: RegexSet,
17641787

@@ -2102,6 +2125,7 @@ impl Default for BindgenOptions {
21022125
default_enum_style: Default::default(),
21032126
bitfield_enums: Default::default(),
21042127
newtype_enums: Default::default(),
2128+
newtype_global_enums: Default::default(),
21052129
rustified_enums: Default::default(),
21062130
rustified_non_exhaustive_enums: Default::default(),
21072131
constified_enums: Default::default(),

src/options.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ where
6363
.value_name("regex")
6464
.multiple_occurrences(true)
6565
.number_of_values(1),
66+
Arg::new("newtype-global-enum")
67+
.long("newtype-global-enum")
68+
.help("Mark any enum whose name matches <regex> as a global newtype.")
69+
.value_name("regex")
70+
.multiple_occurrences(true)
71+
.number_of_values(1),
6672
Arg::new("rustified-enum")
6773
.long("rustified-enum")
6874
.help("Mark any enum whose name matches <regex> as a Rust enum.")
@@ -573,6 +579,12 @@ where
573579
}
574580
}
575581

582+
if let Some(newtypes) = matches.values_of("newtype-global-enum") {
583+
for regex in newtypes {
584+
builder = builder.newtype_global_enum(regex);
585+
}
586+
}
587+
576588
if let Some(rustifieds) = matches.values_of("rustified-enum") {
577589
for regex in rustifieds {
578590
builder = builder.rustified_enum(regex);

tests/expectations/tests/newtype-global-enum.rs

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/headers/newtype-global-enum.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// bindgen-flags: --newtype-global-enum "Foo" --rust-target 1.28 -- -std=c++11
2+
3+
enum Foo {
4+
Bar = 1 << 1,
5+
Baz = 1 << 2,
6+
Duplicated = 1 << 2,
7+
Negative = -3,
8+
};

0 commit comments

Comments
 (0)