summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Poveda <christian.poveda@ferrous-systems.com>2022-09-06 16:59:49 -0500
committerDarren Kulp <darren@kulp.ch>2022-09-11 09:27:58 -0400
commit61636e94ca315278d9ac5f1210ffca6cca697428 (patch)
tree6843df800e05b92043f0a42efbac788c740e18c8 /src
parent8b29355ca0ce54e941d398ef9a605e9b5c0f20ae (diff)
add `--newtype-global-enum` option
Diffstat (limited to 'src')
-rw-r--r--src/codegen/mod.rs51
-rw-r--r--src/ir/enum_ty.rs19
-rw-r--r--src/lib.rs34
-rw-r--r--src/options.rs12
4 files changed, 98 insertions, 18 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index ca4cbf23..9a55ea37 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -2577,6 +2577,8 @@ pub enum EnumVariation {
NewType {
/// Indicates whether the newtype will have bitwise operators
is_bitfield: bool,
+ /// Indicates whether the variants will be represented as global constants
+ is_global: bool,
},
/// The code for this enum will use consts
Consts,
@@ -2614,16 +2616,26 @@ impl std::str::FromStr for EnumVariation {
"rust_non_exhaustive" => Ok(EnumVariation::Rust {
non_exhaustive: true,
}),
- "bitfield" => Ok(EnumVariation::NewType { is_bitfield: true }),
+ "bitfield" => Ok(EnumVariation::NewType {
+ is_bitfield: true,
+ is_global: false,
+ }),
"consts" => Ok(EnumVariation::Consts),
"moduleconsts" => Ok(EnumVariation::ModuleConsts),
- "newtype" => Ok(EnumVariation::NewType { is_bitfield: false }),
+ "newtype" => Ok(EnumVariation::NewType {
+ is_bitfield: false,
+ is_global: false,
+ }),
+ "newtype_global" => Ok(EnumVariation::NewType {
+ is_bitfield: false,
+ is_global: true,
+ }),
_ => Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
concat!(
"Got an invalid EnumVariation. Accepted values ",
"are 'rust', 'rust_non_exhaustive', 'bitfield', 'consts',",
- "'moduleconsts', and 'newtype'."
+ "'moduleconsts', 'newtype' and 'newtype_global'."
),
)),
}
@@ -2644,6 +2656,7 @@ enum EnumBuilder<'a> {
canonical_name: &'a str,
tokens: proc_macro2::TokenStream,
is_bitfield: bool,
+ is_global: bool,
},
Consts {
variants: Vec<proc_macro2::TokenStream>,
@@ -2684,7 +2697,10 @@ impl<'a> EnumBuilder<'a> {
let ident = Ident::new(name, Span::call_site());
match enum_variation {
- EnumVariation::NewType { is_bitfield } => EnumBuilder::NewType {
+ EnumVariation::NewType {
+ is_bitfield,
+ is_global,
+ } => EnumBuilder::NewType {
codegen_depth: enum_codegen_depth,
canonical_name: name,
tokens: quote! {
@@ -2692,6 +2708,7 @@ impl<'a> EnumBuilder<'a> {
pub struct #ident (pub #repr);
},
is_bitfield,
+ is_global,
},
EnumVariation::Rust { .. } => {
@@ -2792,17 +2809,29 @@ impl<'a> EnumBuilder<'a> {
}
}
- EnumBuilder::NewType { canonical_name, .. } => {
+ EnumBuilder::NewType {
+ canonical_name,
+ is_global,
+ ..
+ } => {
if ctx.options().rust_features().associated_const && is_ty_named
{
let enum_ident = ctx.rust_ident(canonical_name);
let variant_ident = ctx.rust_ident(variant_name);
- result.push(quote! {
- impl #enum_ident {
- #doc
- pub const #variant_ident : #rust_ty = #rust_ty ( #expr );
- }
- });
+ let tokens = quote! {
+ #doc
+ pub const #variant_ident : #rust_ty = #rust_ty ( #expr );
+ };
+
+ if is_global {
+ result.push(tokens);
+ } else {
+ result.push(quote! {
+ impl #enum_ident {
+ #tokens
+ }
+ });
+ }
} else {
let ident = ctx.rust_ident(match mangling_prefix {
Some(prefix) => {
diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs
index 97455c91..2b039a4f 100644
--- a/src/ir/enum_ty.rs
+++ b/src/ir/enum_ty.rs
@@ -187,10 +187,25 @@ impl Enum {
&ctx.options().bitfield_enums,
item,
) {
- EnumVariation::NewType { is_bitfield: true }
+ EnumVariation::NewType {
+ is_bitfield: true,
+ is_global: false,
+ }
} else if self.is_matching_enum(ctx, &ctx.options().newtype_enums, item)
{
- EnumVariation::NewType { is_bitfield: false }
+ EnumVariation::NewType {
+ is_bitfield: false,
+ is_global: false,
+ }
+ } else if self.is_matching_enum(
+ ctx,
+ &ctx.options().newtype_global_enums,
+ item,
+ ) {
+ EnumVariation::NewType {
+ is_bitfield: false,
+ is_global: true,
+ }
} else if self.is_matching_enum(
ctx,
&ctx.options().rustified_enums,
diff --git a/src/lib.rs b/src/lib.rs
index fb02fe16..112df665 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -279,11 +279,19 @@ impl Builder {
codegen::EnumVariation::Rust {
non_exhaustive: true,
} => "rust_non_exhaustive",
- codegen::EnumVariation::NewType { is_bitfield: true } => {
- "bitfield"
- }
- codegen::EnumVariation::NewType { is_bitfield: false } => {
- "newtype"
+ codegen::EnumVariation::NewType {
+ is_bitfield: true,
+ ..
+ } => "bitfield",
+ codegen::EnumVariation::NewType {
+ is_bitfield: false,
+ is_global,
+ } => {
+ if is_global {
+ "newtype_global"
+ } else {
+ "newtype"
+ }
}
codegen::EnumVariation::Consts => "consts",
codegen::EnumVariation::ModuleConsts => "moduleconsts",
@@ -984,6 +992,18 @@ impl Builder {
self
}
+ /// Mark the given enum (or set of enums, if using a pattern) as a newtype
+ /// whose variants are exposed as global constants.
+ ///
+ /// Regular expressions are supported.
+ ///
+ /// This makes bindgen generate a type that isn't a Rust `enum`. Regular
+ /// expressions are supported.
+ pub fn newtype_global_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.newtype_global_enums.insert(arg);
+ self
+ }
+
/// Mark the given enum (or set of enums, if using a pattern) as a Rust
/// enum.
///
@@ -1759,6 +1779,9 @@ struct BindgenOptions {
/// The enum patterns to mark an enum as a newtype.
newtype_enums: RegexSet,
+ /// The enum patterns to mark an enum as a global newtype.
+ newtype_global_enums: RegexSet,
+
/// The enum patterns to mark an enum as a Rust enum.
rustified_enums: RegexSet,
@@ -2102,6 +2125,7 @@ impl Default for BindgenOptions {
default_enum_style: Default::default(),
bitfield_enums: Default::default(),
newtype_enums: Default::default(),
+ newtype_global_enums: Default::default(),
rustified_enums: Default::default(),
rustified_non_exhaustive_enums: Default::default(),
constified_enums: Default::default(),
diff --git a/src/options.rs b/src/options.rs
index 83da21f4..4db3fd57 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -63,6 +63,12 @@ where
.value_name("regex")
.multiple_occurrences(true)
.number_of_values(1),
+ Arg::new("newtype-global-enum")
+ .long("newtype-global-enum")
+ .help("Mark any enum whose name matches <regex> as a global newtype.")
+ .value_name("regex")
+ .multiple_occurrences(true)
+ .number_of_values(1),
Arg::new("rustified-enum")
.long("rustified-enum")
.help("Mark any enum whose name matches <regex> as a Rust enum.")
@@ -573,6 +579,12 @@ where
}
}
+ if let Some(newtypes) = matches.values_of("newtype-global-enum") {
+ for regex in newtypes {
+ builder = builder.newtype_global_enum(regex);
+ }
+ }
+
if let Some(rustifieds) = matches.values_of("rustified-enum") {
for regex in rustifieds {
builder = builder.rustified_enum(regex);