From 0b293e1f6d9b26fb8dcc5113c3f04c47b588d04f Mon Sep 17 00:00:00 2001 From: Daniel Brooks Date: Sun, 3 Jun 2018 11:35:07 -0700 Subject: [PATCH 1/3] Add an option to set the default codegen style for all enums --- src/codegen/mod.rs | 37 ++++++++++++++-- src/lib.rs | 21 +++++++++ src/options.rs | 13 +++++- .../tests/bitfield-32bit-overflow.rs | 2 - tests/expectations/tests/bitfield_align.rs | 2 - .../tests/enum-default-bitfield.rs | 44 +++++++++++++++++++ .../expectations/tests/enum-default-consts.rs | 12 +++++ .../expectations/tests/enum-default-module.rs | 14 ++++++ tests/expectations/tests/enum-default-rust.rs | 15 +++++++ .../tests/issue-739-pointer-wide-bitfield.rs | 2 - .../tests/struct_with_bitfields.rs | 2 - tests/headers/enum-default-bitfield.h | 11 +++++ tests/headers/enum-default-consts.h | 11 +++++ tests/headers/enum-default-module.h | 11 +++++ tests/headers/enum-default-rust.h | 11 +++++ 15 files changed, 195 insertions(+), 13 deletions(-) create mode 100644 tests/expectations/tests/enum-default-bitfield.rs create mode 100644 tests/expectations/tests/enum-default-consts.rs create mode 100644 tests/expectations/tests/enum-default-module.rs create mode 100644 tests/expectations/tests/enum-default-rust.rs create mode 100644 tests/headers/enum-default-bitfield.h create mode 100644 tests/headers/enum-default-consts.h create mode 100644 tests/headers/enum-default-module.h create mode 100644 tests/headers/enum-default-rust.h diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index b6aabb1758..4575f9b234 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -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}; @@ -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 } @@ -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 { + match s.as_ref() { + "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 { @@ -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_variant }; let mut attrs = vec![]; diff --git a/src/lib.rs b/src/lib.rs index 9f90ffb77a..38b914940e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; @@ -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_variant != Default::default() { + output_vector.push("--default-enum-variant=".into()); + output_vector.push(match self.options.default_enum_variant { + codegen::EnumVariation::Rust => "rust", + codegen::EnumVariation::Bitfield => "bitfield", + codegen::EnumVariation::Consts => "consts", + codegen::EnumVariation::ModuleConsts => "moduleconsts", + }.into()) + }; + self.options .bitfield_enums .get_items() @@ -730,6 +741,12 @@ impl Builder { } + /// Set the default type of code to generate for enums + pub fn default_enum_variant(mut self, arg: codegen::EnumVariation) -> Builder { + self.options.default_enum_variant = arg; + self + } + /// Mark the given enum (or set of enums, if using a pattern) as being /// bitfield-like. Regular expressions are supported. /// @@ -1240,6 +1257,9 @@ struct BindgenOptions { /// Whitelisted variables. See docs for `whitelisted_types` for more. whitelisted_vars: RegexSet, + /// The default type of code to generate for enums + default_enum_variant: codegen::EnumVariation, + /// The enum patterns to mark an enum as bitfield. bitfield_enums: RegexSet, @@ -1458,6 +1478,7 @@ impl Default for BindgenOptions { whitelisted_types: Default::default(), whitelisted_functions: Default::default(), whitelisted_vars: Default::default(), + default_enum_variant: Default::default(), bitfield_enums: Default::default(), rustified_enums: Default::default(), constified_enum_modules: Default::default(), diff --git a/src/options.rs b/src/options.rs index b3ddbbfdb3..9405aff92e 100644 --- a/src/options.rs +++ b/src/options.rs @@ -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}; @@ -26,6 +26,13 @@ where Arg::with_name("header") .help("C or C++ header file") .required(true), + Arg::with_name("default-enum-variant") + .long("default-enum-variant") + .help("choose one") + .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 as a set of \ @@ -303,6 +310,10 @@ where builder = builder.rust_target(RustTarget::from_str(rust_target)?); } + if let Some(variant) = matches.value_of("default-enum-variant") { + builder = builder.default_enum_variant(EnumVariation::from_str(variant)?) + } + if let Some(bitfields) = matches.values_of("bitfield-enum") { for regex in bitfields { builder = builder.bitfield_enum(regex); diff --git a/tests/expectations/tests/bitfield-32bit-overflow.rs b/tests/expectations/tests/bitfield-32bit-overflow.rs index f64299a6ab..7270649e6b 100644 --- a/tests/expectations/tests/bitfield-32bit-overflow.rs +++ b/tests/expectations/tests/bitfield-32bit-overflow.rs @@ -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 diff --git a/tests/expectations/tests/bitfield_align.rs b/tests/expectations/tests/bitfield_align.rs index d7ee04456d..9821aa6fdf 100644 --- a/tests/expectations/tests/bitfield_align.rs +++ b/tests/expectations/tests/bitfield_align.rs @@ -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 diff --git a/tests/expectations/tests/enum-default-bitfield.rs b/tests/expectations/tests/enum-default-bitfield.rs new file mode 100644 index 0000000000..19172d0b49 --- /dev/null +++ b/tests/expectations/tests/enum-default-bitfield.rs @@ -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 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 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; +} diff --git a/tests/expectations/tests/enum-default-consts.rs b/tests/expectations/tests/enum-default-consts.rs new file mode 100644 index 0000000000..6ced4de085 --- /dev/null +++ b/tests/expectations/tests/enum-default-consts.rs @@ -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; +} diff --git a/tests/expectations/tests/enum-default-module.rs b/tests/expectations/tests/enum-default-module.rs new file mode 100644 index 0000000000..953793c378 --- /dev/null +++ b/tests/expectations/tests/enum-default-module.rs @@ -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; +} diff --git a/tests/expectations/tests/enum-default-rust.rs b/tests/expectations/tests/enum-default-rust.rs new file mode 100644 index 0000000000..1400e37395 --- /dev/null +++ b/tests/expectations/tests/enum-default-rust.rs @@ -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; +} diff --git a/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs b/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs index 806b3f161d..81c32bbf33 100644 --- a/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs +++ b/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs @@ -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 diff --git a/tests/expectations/tests/struct_with_bitfields.rs b/tests/expectations/tests/struct_with_bitfields.rs index 85f37e103b..a45472d5a9 100644 --- a/tests/expectations/tests/struct_with_bitfields.rs +++ b/tests/expectations/tests/struct_with_bitfields.rs @@ -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 diff --git a/tests/headers/enum-default-bitfield.h b/tests/headers/enum-default-bitfield.h new file mode 100644 index 0000000000..a73f2838b8 --- /dev/null +++ b/tests/headers/enum-default-bitfield.h @@ -0,0 +1,11 @@ +// bindgen-flags: --default-enum-variant=bitfield --constified-enum-module=Neg + +enum Foo { + Bar = 0, + Qux +}; + +enum Neg { + MinusOne = -1, + One = 1, +}; diff --git a/tests/headers/enum-default-consts.h b/tests/headers/enum-default-consts.h new file mode 100644 index 0000000000..17f0afc4e0 --- /dev/null +++ b/tests/headers/enum-default-consts.h @@ -0,0 +1,11 @@ +// bindgen-flags: --default-enum-variant=consts --constified-enum-module=Neg + +enum Foo { + Bar = 0, + Qux +}; + +enum Neg { + MinusOne = -1, + One = 1, +}; diff --git a/tests/headers/enum-default-module.h b/tests/headers/enum-default-module.h new file mode 100644 index 0000000000..e586cca29d --- /dev/null +++ b/tests/headers/enum-default-module.h @@ -0,0 +1,11 @@ +// bindgen-flags: --default-enum-variant=moduleconsts --constified-enum-module=Neg + +enum Foo { + Bar = 0, + Qux +}; + +enum Neg { + MinusOne = -1, + One = 1, +}; diff --git a/tests/headers/enum-default-rust.h b/tests/headers/enum-default-rust.h new file mode 100644 index 0000000000..797863c3cb --- /dev/null +++ b/tests/headers/enum-default-rust.h @@ -0,0 +1,11 @@ +// bindgen-flags: --default-enum-variant=rust --constified-enum-module=Neg + +enum Foo { + Bar = 0, + Qux +}; + +enum Neg { + MinusOne = -1, + One = 1, +}; From 52d7f8d454413a72896c3c06b9213a42b7042b04 Mon Sep 17 00:00:00 2001 From: Daniel Brooks Date: Mon, 4 Jun 2018 05:35:17 -0700 Subject: [PATCH 2/3] Rename from "enum variant" to "enum style" --- src/codegen/mod.rs | 2 +- src/lib.rs | 19 +++++++++---------- src/options.rs | 10 +++++----- tests/headers/enum-default-bitfield.h | 2 +- tests/headers/enum-default-consts.h | 2 +- tests/headers/enum-default-module.h | 2 +- tests/headers/enum-default-rust.h | 2 +- 7 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 4575f9b234..8c602eae11 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -2521,7 +2521,7 @@ impl CodeGenerator for Enum { } else if self.is_rustified_enum(ctx, item) { EnumVariation::Rust } else { - ctx.options().default_enum_variant + ctx.options().default_enum_style }; let mut attrs = vec![]; diff --git a/src/lib.rs b/src/lib.rs index 38b914940e..9a2d4f14e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -204,15 +204,15 @@ impl Builder { output_vector.push("--rust-target".into()); output_vector.push(self.options.rust_target.into()); - if self.options.default_enum_variant != Default::default() { + if self.options.default_enum_style != Default::default() { output_vector.push("--default-enum-variant=".into()); - output_vector.push(match self.options.default_enum_variant { + 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 @@ -740,10 +740,9 @@ impl Builder { self.whitelist_var(arg) } - - /// Set the default type of code to generate for enums - pub fn default_enum_variant(mut self, arg: codegen::EnumVariation) -> Builder { - self.options.default_enum_variant = 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 } @@ -1257,8 +1256,8 @@ struct BindgenOptions { /// Whitelisted variables. See docs for `whitelisted_types` for more. whitelisted_vars: RegexSet, - /// The default type of code to generate for enums - default_enum_variant: codegen::EnumVariation, + /// 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, @@ -1478,7 +1477,7 @@ impl Default for BindgenOptions { whitelisted_types: Default::default(), whitelisted_functions: Default::default(), whitelisted_vars: Default::default(), - default_enum_variant: Default::default(), + default_enum_style: Default::default(), bitfield_enums: Default::default(), rustified_enums: Default::default(), constified_enum_modules: Default::default(), diff --git a/src/options.rs b/src/options.rs index 9405aff92e..97b2556b7b 100644 --- a/src/options.rs +++ b/src/options.rs @@ -26,9 +26,9 @@ where Arg::with_name("header") .help("C or C++ header file") .required(true), - Arg::with_name("default-enum-variant") - .long("default-enum-variant") - .help("choose one") + 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"]) @@ -310,8 +310,8 @@ where builder = builder.rust_target(RustTarget::from_str(rust_target)?); } - if let Some(variant) = matches.value_of("default-enum-variant") { - builder = builder.default_enum_variant(EnumVariation::from_str(variant)?) + 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") { diff --git a/tests/headers/enum-default-bitfield.h b/tests/headers/enum-default-bitfield.h index a73f2838b8..be2841329b 100644 --- a/tests/headers/enum-default-bitfield.h +++ b/tests/headers/enum-default-bitfield.h @@ -1,4 +1,4 @@ -// bindgen-flags: --default-enum-variant=bitfield --constified-enum-module=Neg +// bindgen-flags: --default-enum-style=bitfield --constified-enum-module=Neg enum Foo { Bar = 0, diff --git a/tests/headers/enum-default-consts.h b/tests/headers/enum-default-consts.h index 17f0afc4e0..448c3030a8 100644 --- a/tests/headers/enum-default-consts.h +++ b/tests/headers/enum-default-consts.h @@ -1,4 +1,4 @@ -// bindgen-flags: --default-enum-variant=consts --constified-enum-module=Neg +// bindgen-flags: --default-enum-style=consts --constified-enum-module=Neg enum Foo { Bar = 0, diff --git a/tests/headers/enum-default-module.h b/tests/headers/enum-default-module.h index e586cca29d..a2f3d7adfd 100644 --- a/tests/headers/enum-default-module.h +++ b/tests/headers/enum-default-module.h @@ -1,4 +1,4 @@ -// bindgen-flags: --default-enum-variant=moduleconsts --constified-enum-module=Neg +// bindgen-flags: --default-enum-style=moduleconsts --constified-enum-module=Neg enum Foo { Bar = 0, diff --git a/tests/headers/enum-default-rust.h b/tests/headers/enum-default-rust.h index 797863c3cb..282c62f3ff 100644 --- a/tests/headers/enum-default-rust.h +++ b/tests/headers/enum-default-rust.h @@ -1,4 +1,4 @@ -// bindgen-flags: --default-enum-variant=rust --constified-enum-module=Neg +// bindgen-flags: --default-enum-style=rust --constified-enum-module=Neg enum Foo { Bar = 0, From 393e77952af3c42362b8cd5755ce4df74dfe9e6d Mon Sep 17 00:00:00 2001 From: Daniel Brooks Date: Mon, 4 Jun 2018 05:38:06 -0700 Subject: [PATCH 3/3] remove unnecessary as_ref --- src/codegen/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 8c602eae11..387ff49541 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -2152,7 +2152,7 @@ impl std::str::FromStr for EnumVariation { /// Create a `EnumVariation` from a string. fn from_str(s: &str) -> Result { - match s.as_ref() { + match s { "rust" => Ok(EnumVariation::Rust), "bitfield" => Ok(EnumVariation::Bitfield), "consts" => Ok(EnumVariation::Consts),