Skip to content

Commit

Permalink
Add option to generate safe and unsafe conversions for rustified enums
Browse files Browse the repository at this point in the history
  • Loading branch information
jbaublitz committed Oct 23, 2024
1 parent 07bbd04 commit bd3a560
Show file tree
Hide file tree
Showing 10 changed files with 602 additions and 144 deletions.
38 changes: 24 additions & 14 deletions bindgen-cli/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use bindgen::callbacks::TypeKind;
use bindgen::{
builder, Abi, AliasVariation, Builder, CodegenConfig, EnumVariation,
FieldVisibilityKind, Formatter, MacroTypeVariation, NonCopyUnionStyle,
RegexSet, RustTarget, DEFAULT_ANON_FIELDS_PREFIX, RUST_TARGET_STRINGS,
RegexSet, RustEnumOptions, RustTarget, DEFAULT_ANON_FIELDS_PREFIX,
RUST_TARGET_STRINGS,
};
use clap::error::{Error, ErrorKind};
use clap::{CommandFactory, Parser};
Expand Down Expand Up @@ -77,6 +78,21 @@ fn parse_abi_override(abi_override: &str) -> Result<(Abi, String), Error> {
Ok((abi, regex.to_owned()))
}

fn parse_rustified_enum(
rustified_enum: &str,
) -> Result<(RustEnumOptions, String), Error> {
let (regex, options) = match rustified_enum.rsplit_once('=') {
Some((regex, options)) => (regex, options),
None => (rustified_enum, ""),
};

let options = options
.parse()
.map_err(|err| Error::raw(ErrorKind::InvalidValue, err))?;

Ok((options, regex.to_owned()))
}

fn parse_custom_derive(
custom_derive: &str,
) -> Result<(Vec<String>, String), Error> {
Expand Down Expand Up @@ -150,12 +166,11 @@ struct BindgenCommand {
/// Mark any enum whose name matches REGEX as a global newtype.
#[arg(long, value_name = "REGEX")]
newtype_global_enum: Vec<String>,
/// Mark any enum whose name matches REGEX as a Rust enum.
#[arg(long, value_name = "REGEX")]
rustified_enum: Vec<String>,
/// Mark any enum whose name matches REGEX as a non-exhaustive Rust enum.
#[arg(long, value_name = "REGEX")]
rustified_non_exhaustive_enum: Vec<String>,
/// Mark any enum whose name matches the provided regex as a Rust enum. This parameter takes
/// options in the shape REGEX or REGEX=OPTIONS where OPTIONS can be a comma separated list of
/// options from non_exhaustive, try_from_raw, and from_raw_unchecked.
#[arg(long, value_parser = parse_rustified_enum)]
rustified_enum: Vec<(RustEnumOptions, String)>,
/// Mark any enum whose name matches REGEX as a series of constants.
#[arg(long, value_name = "REGEX")]
constified_enum: Vec<String>,
Expand Down Expand Up @@ -523,7 +538,6 @@ where
newtype_enum,
newtype_global_enum,
rustified_enum,
rustified_non_exhaustive_enum,
constified_enum,
constified_enum_module,
default_macro_constant_type,
Expand Down Expand Up @@ -690,12 +704,8 @@ where
builder = builder.newtype_global_enum(regex);
}

for regex in rustified_enum {
builder = builder.rustified_enum(regex);
}

for regex in rustified_non_exhaustive_enum {
builder = builder.rustified_non_exhaustive_enum(regex);
for (options, regex) in rustified_enum {
builder = builder.rustified_enum(options, regex);
}

for regex in constified_enum {
Expand Down
2 changes: 2 additions & 0 deletions bindgen-integration/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ fn setup_macro_test() {
.enable_cxx_namespaces()
.default_enum_style(EnumVariation::Rust {
non_exhaustive: false,
safe_conversion: false,
unsafe_conversion: false,
})
.raw_line("pub use self::root::*;")
.raw_line("extern { fn my_prefixed_function_to_remove(i: i32); }")
Expand Down
100 changes: 100 additions & 0 deletions bindgen-tests/tests/expectations/tests/issue-2646.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions bindgen-tests/tests/headers/issue-2646.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// bindgen-flags: --rustified-enum 'Plain.*' --rustified-enum 'TryFromRaw.*=try_from_raw' --rustified-enum='FromRawUnchecked.*=from_raw_unchecked' --rustified-enum='Both.*=try_from_raw,from_raw_unchecked' --rustified-enum 'NonExhaustive.*=non_exhaustive'

enum Plain {
Plain1,
Plain2,
Plain3
};

enum TryFromRaw {
TFR1 = -1,
TFR2 = 5,
TFR3
};

enum FromRawUnchecked {
FRU1 = 6,
FRU2 = 10,
FRU3 = 11,
};

enum Both {
Both1,
Both2 = -1,
Both3,
};

enum NonExhaustive {
Ex1,
Ex2,
};
Binary file added bindgen/codegen/.mod.rs.swp
Binary file not shown.
Loading

0 comments on commit bd3a560

Please sign in to comment.