Skip to content

Add an option to set the default codegen style for all enums #1328

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use ir::var::Var;
use quote;
use proc_macro2::{self, Term, Span};

use std;
use std::borrow::Cow;
use std::cell::Cell;
use std::collections::{HashSet, VecDeque};
Expand Down Expand Up @@ -2103,11 +2104,15 @@ impl MethodCodegen for Method {
}

/// A helper type that represents different enum variations.
#[derive(Copy, Clone)]
enum EnumVariation {
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum EnumVariation {
/// The code for this enum will use a Rust enum
Rust,
/// The code for this enum will use a bitfield
Bitfield,
/// The code for this enum will use consts
Consts,
/// The code for this enum will use a module containing consts
ModuleConsts
}

Expand Down Expand Up @@ -2136,6 +2141,31 @@ impl EnumVariation {
}
}

impl Default for EnumVariation {
fn default() -> EnumVariation {
EnumVariation::Consts
}
}

impl std::str::FromStr for EnumVariation {
type Err = std::io::Error;

/// Create a `EnumVariation` from a string.
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"rust" => Ok(EnumVariation::Rust),
"bitfield" => Ok(EnumVariation::Bitfield),
"consts" => Ok(EnumVariation::Consts),
"moduleconsts" => Ok(EnumVariation::ModuleConsts),
_ => Err(std::io::Error::new(std::io::ErrorKind::InvalidInput,
concat!("Got an invalid EnumVariation. Accepted values ",
"are 'rust', 'bitfield', 'consts', and ",
"'moduleconsts'."))),
}
}
}


/// A helper type to construct different enum variations.
enum EnumBuilder<'a> {
Rust {
Expand Down Expand Up @@ -2491,8 +2521,7 @@ impl CodeGenerator for Enum {
} else if self.is_rustified_enum(ctx, item) {
EnumVariation::Rust
} else {
// We generate consts by default
EnumVariation::Consts
ctx.options().default_enum_style
};

let mut attrs = vec![];
Expand Down
20 changes: 20 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ use ir::context::{BindgenContext, ItemId};
use ir::item::Item;
use parse::{ClangItemParser, ParseError};
use regex_set::RegexSet;
pub use codegen::EnumVariation;

use std::borrow::Cow;
use std::collections::HashMap;
Expand Down Expand Up @@ -203,6 +204,16 @@ impl Builder {
output_vector.push("--rust-target".into());
output_vector.push(self.options.rust_target.into());

if self.options.default_enum_style != Default::default() {
output_vector.push("--default-enum-variant=".into());
output_vector.push(match self.options.default_enum_style {
codegen::EnumVariation::Rust => "rust",
codegen::EnumVariation::Bitfield => "bitfield",
codegen::EnumVariation::Consts => "consts",
codegen::EnumVariation::ModuleConsts => "moduleconsts",
}.into())
}

self.options
.bitfield_enums
.get_items()
Expand Down Expand Up @@ -729,6 +740,11 @@ impl Builder {
self.whitelist_var(arg)
}

/// Set the default style of code to generate for enums
pub fn default_enum_style(mut self, arg: codegen::EnumVariation) -> Builder {
self.options.default_enum_style = arg;
self
}

/// Mark the given enum (or set of enums, if using a pattern) as being
/// bitfield-like. Regular expressions are supported.
Expand Down Expand Up @@ -1240,6 +1256,9 @@ struct BindgenOptions {
/// Whitelisted variables. See docs for `whitelisted_types` for more.
whitelisted_vars: RegexSet,

/// The default style of code to generate for enums
default_enum_style: codegen::EnumVariation,

/// The enum patterns to mark an enum as bitfield.
bitfield_enums: RegexSet,

Expand Down Expand Up @@ -1458,6 +1477,7 @@ impl Default for BindgenOptions {
whitelisted_types: Default::default(),
whitelisted_functions: Default::default(),
whitelisted_vars: Default::default(),
default_enum_style: Default::default(),
bitfield_enums: Default::default(),
rustified_enums: Default::default(),
constified_enum_modules: Default::default(),
Expand Down
13 changes: 12 additions & 1 deletion src/options.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use bindgen::{Builder, CodegenConfig, RUST_TARGET_STRINGS, RustTarget, builder};
use bindgen::{Builder, CodegenConfig, RUST_TARGET_STRINGS, RustTarget, builder, EnumVariation};
use clap::{App, Arg};
use std::fs::File;
use std::io::{self, Error, ErrorKind, Write, stderr};
Expand Down Expand Up @@ -26,6 +26,13 @@ where
Arg::with_name("header")
.help("C or C++ header file")
.required(true),
Arg::with_name("default-enum-style")
.long("default-enum-style")
.help("The default style of code used to generate enums.")
.value_name("variant")
.default_value("consts")
.possible_values(&["consts", "moduleconsts", "bitfield", "rust"])
.multiple(false),
Arg::with_name("bitfield-enum")
.long("bitfield-enum")
.help("Mark any enum whose name matches <regex> as a set of \
Expand Down Expand Up @@ -303,6 +310,10 @@ where
builder = builder.rust_target(RustTarget::from_str(rust_target)?);
}

if let Some(variant) = matches.value_of("default-enum-style") {
builder = builder.default_enum_style(EnumVariation::from_str(variant)?)
}

if let Some(bitfields) = matches.values_of("bitfield-enum") {
for regex in bitfields {
builder = builder.bitfield_enum(regex);
Expand Down
2 changes: 0 additions & 2 deletions tests/expectations/tests/bitfield-32bit-overflow.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* automatically generated by rust-bindgen */


#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]


#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage, Align>
Expand Down
2 changes: 0 additions & 2 deletions tests/expectations/tests/bitfield_align.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* automatically generated by rust-bindgen */


#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]


#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage, Align>
Expand Down
44 changes: 44 additions & 0 deletions tests/expectations/tests/enum-default-bitfield.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* automatically generated by rust-bindgen */

#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]

impl Foo {
pub const Bar: Foo = Foo(0);
}
impl Foo {
pub const Qux: Foo = Foo(1);
}
impl ::std::ops::BitOr<Foo> for Foo {
type Output = Self;
#[inline]
fn bitor(self, other: Self) -> Self {
Foo(self.0 | other.0)
}
}
impl ::std::ops::BitOrAssign for Foo {
#[inline]
fn bitor_assign(&mut self, rhs: Foo) {
self.0 |= rhs.0;
}
}
impl ::std::ops::BitAnd<Foo> for Foo {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self {
Foo(self.0 & other.0)
}
}
impl ::std::ops::BitAndAssign for Foo {
#[inline]
fn bitand_assign(&mut self, rhs: Foo) {
self.0 &= rhs.0;
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Foo(pub u32);
pub mod Neg {
pub type Type = i32;
pub const MinusOne: Type = -1;
pub const One: Type = 1;
}
12 changes: 12 additions & 0 deletions tests/expectations/tests/enum-default-consts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* automatically generated by rust-bindgen */

#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]

pub const Foo_Bar: Foo = 0;
pub const Foo_Qux: Foo = 1;
pub type Foo = u32;
pub mod Neg {
pub type Type = i32;
pub const MinusOne: Type = -1;
pub const One: Type = 1;
}
14 changes: 14 additions & 0 deletions tests/expectations/tests/enum-default-module.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* automatically generated by rust-bindgen */

#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]

pub mod Foo {
pub type Type = u32;
pub const Bar: Type = 0;
pub const Qux: Type = 1;
}
pub mod Neg {
pub type Type = i32;
pub const MinusOne: Type = -1;
pub const One: Type = 1;
}
15 changes: 15 additions & 0 deletions tests/expectations/tests/enum-default-rust.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* automatically generated by rust-bindgen */

#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
Bar = 0,
Qux = 1,
}
pub mod Neg {
pub type Type = i32;
pub const MinusOne: Type = -1;
pub const One: Type = 1;
}
2 changes: 0 additions & 2 deletions tests/expectations/tests/issue-739-pointer-wide-bitfield.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* automatically generated by rust-bindgen */


#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]


#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage, Align>
Expand Down
2 changes: 0 additions & 2 deletions tests/expectations/tests/struct_with_bitfields.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* automatically generated by rust-bindgen */


#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]


#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage, Align>
Expand Down
11 changes: 11 additions & 0 deletions tests/headers/enum-default-bitfield.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// bindgen-flags: --default-enum-style=bitfield --constified-enum-module=Neg

enum Foo {
Bar = 0,
Qux
};

enum Neg {
MinusOne = -1,
One = 1,
};
11 changes: 11 additions & 0 deletions tests/headers/enum-default-consts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// bindgen-flags: --default-enum-style=consts --constified-enum-module=Neg

enum Foo {
Bar = 0,
Qux
};

enum Neg {
MinusOne = -1,
One = 1,
};
11 changes: 11 additions & 0 deletions tests/headers/enum-default-module.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// bindgen-flags: --default-enum-style=moduleconsts --constified-enum-module=Neg

enum Foo {
Bar = 0,
Qux
};

enum Neg {
MinusOne = -1,
One = 1,
};
11 changes: 11 additions & 0 deletions tests/headers/enum-default-rust.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// bindgen-flags: --default-enum-style=rust --constified-enum-module=Neg

enum Foo {
Bar = 0,
Qux
};

enum Neg {
MinusOne = -1,
One = 1,
};