diff options
author | Christian Poveda <christian.poveda@ferrous-systems.com> | 2022-09-06 16:59:49 -0500 |
---|---|---|
committer | Darren Kulp <darren@kulp.ch> | 2022-09-11 09:27:58 -0400 |
commit | 61636e94ca315278d9ac5f1210ffca6cca697428 (patch) | |
tree | 6843df800e05b92043f0a42efbac788c740e18c8 /src | |
parent | 8b29355ca0ce54e941d398ef9a605e9b5c0f20ae (diff) |
add `--newtype-global-enum` option
Diffstat (limited to 'src')
-rw-r--r-- | src/codegen/mod.rs | 51 | ||||
-rw-r--r-- | src/ir/enum_ty.rs | 19 | ||||
-rw-r--r-- | src/lib.rs | 34 | ||||
-rw-r--r-- | src/options.rs | 12 |
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, @@ -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); |