#![allow(unused_qualifications)]
use crate::{
builder,
callbacks::{
AttributeInfo, DeriveInfo, ItemInfo, ParseCallbacks, TypeKind,
},
features::{RustEdition, EARLIEST_STABLE_RUST},
regex_set::RegexSet,
Abi, AliasVariation, Builder, CodegenConfig, EnumVariation,
FieldVisibilityKind, Formatter, MacroTypeVariation, NonCopyUnionStyle,
RustTarget,
};
use clap::{
error::{Error, ErrorKind},
CommandFactory, Parser,
};
use proc_macro2::TokenStream;
use std::io;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::{fs::File, process::exit};
fn rust_target_help() -> String {
format!(
"Version of the Rust compiler to target. Any Rust version after {EARLIEST_STABLE_RUST} is supported. Defaults to {}.",
RustTarget::default()
)
}
fn rust_edition_help() -> String {
format!("Rust edition to target. Defaults to the latest edition supported by the chosen Rust target. Possible values: ({}). ", RustEdition::ALL.map(|e| e.to_string()).join("|"))
}
fn parse_codegen_config(
what_to_generate: &str,
) -> Result<CodegenConfig, Error> {
let mut config = CodegenConfig::empty();
for what in what_to_generate.split(',') {
match what {
"functions" => config.insert(CodegenConfig::FUNCTIONS),
"types" => config.insert(CodegenConfig::TYPES),
"vars" => config.insert(CodegenConfig::VARS),
"methods" => config.insert(CodegenConfig::METHODS),
"constructors" => config.insert(CodegenConfig::CONSTRUCTORS),
"destructors" => config.insert(CodegenConfig::DESTRUCTORS),
otherwise => {
return Err(Error::raw(
ErrorKind::InvalidValue,
format!("Unknown codegen item kind: {otherwise}"),
));
}
}
}
Ok(config)
}
fn parse_rustfmt_config_path(path_str: &str) -> Result<PathBuf, Error> {
let path = Path::new(path_str);
if !path.is_absolute() {
return Err(Error::raw(
ErrorKind::InvalidValue,
"--rustfmt-configuration-file needs to be an absolute path!",
));
}
if path.to_str().is_none() {
return Err(Error::raw(
ErrorKind::InvalidUtf8,
"--rustfmt-configuration-file contains non-valid UTF8 characters.",
));
}
Ok(path.to_path_buf())
}
fn parse_abi_override(abi_override: &str) -> Result<(Abi, String), Error> {
let (regex, abi_str) = abi_override
.rsplit_once('=')
.ok_or_else(|| Error::raw(ErrorKind::InvalidValue, "Missing `=`"))?;
let abi = abi_str
.parse()
.map_err(|err| Error::raw(ErrorKind::InvalidValue, err))?;
Ok((abi, regex.to_owned()))
}
fn parse_custom_derive(
custom_derive: &str,
) -> Result<(Vec<String>, String), Error> {
let (regex, derives) = custom_derive
.rsplit_once('=')
.ok_or_else(|| Error::raw(ErrorKind::InvalidValue, "Missing `=`"))?;
let derives = derives.split(',').map(|s| s.to_owned()).collect();
Ok((derives, regex.to_owned()))
}
fn parse_custom_attribute(
custom_attribute: &str,
) -> Result<(Vec<String>, String), Error> {
let mut brace_level = 0;
let (regex, attributes) = custom_attribute
.rsplit_once(|c| {
match c {
']' => brace_level += 1,
'[' => brace_level -= 1,
_ => {}
}
c == '=' && brace_level == 0
})
.ok_or_else(|| Error::raw(ErrorKind::InvalidValue, "Missing `=`"))?;
let mut brace_level = 0;
let attributes = attributes
.split(|c| {
match c {
']' => brace_level += 1,
'[' => brace_level -= 1,
_ => {}
}
c == ',' && brace_level == 0
})
.map(|s| s.to_owned())
.collect::<Vec<_>>();
for attribute in &attributes {
if let Err(err) = TokenStream::from_str(attribute) {
return Err(Error::raw(ErrorKind::InvalidValue, err));
}
}
Ok((attributes, regex.to_owned()))
}
fn parse_field_attr(
field_attr: &str,
) -> Result<(String, String, String), Error> {
let (type_field, attr) = field_attr.split_once('=').ok_or_else(|| {
Error::raw(ErrorKind::InvalidValue, "Missing `=` in field-attr")
})?;
let (type_name, field_name) =
type_field.rsplit_once("::").ok_or_else(|| {
Error::raw(
ErrorKind::InvalidValue,
"Missing `::` in field-attr. Expected format: TYPE::FIELD=ATTR",
)
})?;
if let Err(err) = TokenStream::from_str(attr) {
return Err(Error::raw(ErrorKind::InvalidValue, err));
}
Ok((type_name.to_owned(), field_name.to_owned(), attr.to_owned()))
}
#[derive(Parser, Debug)]
#[clap(
about = "Generates Rust bindings from C/C++ headers.",
override_usage = "bindgen <FLAGS> <OPTIONS> <HEADER> -- <CLANG_ARGS>...",
trailing_var_arg = true
)]
#[allow(clippy::doc_markdown)]
struct BindgenCommand {
header: Option<String>,
#[arg(long)]
depfile: Option<String>,
#[arg(long, value_name = "STYLE")]
default_enum_style: Option<EnumVariation>,
#[arg(long, value_name = "REGEX")]
bitfield_enum: Vec<String>,
#[arg(long, value_name = "REGEX")]
newtype_enum: Vec<String>,
#[arg(long, value_name = "REGEX")]
newtype_global_enum: Vec<String>,
#[arg(long, value_name = "REGEX")]
rustified_enum: Vec<String>,
#[arg(long, value_name = "REGEX")]
rustified_non_exhaustive_enum: Vec<String>,
#[arg(long, value_name = "REGEX")]
constified_enum: Vec<String>,
#[arg(long, value_name = "REGEX")]
constified_enum_module: Vec<String>,
#[arg(long, value_name = "TYPE")]
default_macro_constant_type: Option<MacroTypeVariation>,
#[arg(long, value_name = "STYLE")]
default_alias_style: Option<AliasVariation>,
#[arg(long, value_name = "REGEX")]
normal_alias: Vec<String>,
#[arg(long, value_name = "REGEX")]
new_type_alias: Vec<String>,
#[arg(long, value_name = "REGEX")]
new_type_alias_deref: Vec<String>,
#[arg(long, value_name = "STYLE")]
default_non_copy_union_style: Option<NonCopyUnionStyle>,
#[arg(long, value_name = "REGEX")]
bindgen_wrapper_union: Vec<String>,
#[arg(long, value_name = "REGEX")]
manually_drop_union: Vec<String>,
#[arg(long, value_name = "TYPE")]
blocklist_type: Vec<String>,
#[arg(long, value_name = "FUNCTION")]
blocklist_function: Vec<String>,
#[arg(long, value_name = "ITEM")]
blocklist_item: Vec<String>,
#[arg(long, value_name = "FILE")]
blocklist_file: Vec<String>,
#[arg(long, value_name = "VAR")]
blocklist_var: Vec<String>,
#[arg(long)]
no_layout_tests: bool,
#[arg(long)]
no_derive_copy: bool,
#[arg(long)]
no_derive_debug: bool,
#[arg(long, hide = true)]
no_derive_default: bool,
#[arg(long)]
impl_debug: bool,
#[arg(long)]
impl_partialeq: bool,
#[arg(long)]
with_derive_default: bool,
#[arg(long)]
with_derive_hash: bool,
#[arg(long)]
with_derive_partialeq: bool,
#[arg(long)]
with_derive_partialord: bool,
#[arg(long)]
with_derive_eq: bool,
#[arg(long)]
with_derive_ord: bool,
#[arg(long)]
no_doc_comments: bool,
#[arg(long)]
no_recursive_allowlist: bool,
#[arg(long)]
objc_extern_crate: bool,
#[arg(long)]
nonnull_references: bool,
#[arg(long)]
generate_block: bool,
#[arg(long)]
generate_cstr: bool,
#[arg(long)]
block_extern_crate: bool,
#[arg(long)]
distrust_clang_mangling: bool,
#[arg(long)]
builtins: bool,
#[arg(long, value_name = "PREFIX")]
ctypes_prefix: Option<String>,
#[arg(long, value_name = "PREFIX")]
anon_fields_prefix: Option<String>,
#[arg(long)]
time_phases: bool,
#[arg(long)]
emit_clang_ast: bool,
#[arg(long)]
emit_ir: bool,
#[arg(long, value_name = "PATH")]
emit_ir_graphviz: Option<String>,
#[arg(long)]
enable_cxx_namespaces: bool,
#[arg(long)]
disable_name_namespacing: bool,
#[arg(long)]
disable_nested_struct_naming: bool,
#[arg(long)]
disable_untagged_union: bool,
#[arg(long)]
disable_header_comment: bool,
#[arg(long)]
ignore_functions: bool,
#[arg(long, value_parser = parse_codegen_config)]
generate: Option<CodegenConfig>,
#[arg(long)]
ignore_methods: bool,
#[arg(long)]
no_convert_floats: bool,
#[arg(long)]
no_prepend_enum_name: bool,
#[arg(long)]
no_include_path_detection: bool,
#[arg(long)]
fit_macro_constant_types: bool,
#[arg(long, value_name = "TYPE")]
opaque_type: Vec<String>,
#[arg(long, short, value_name = "OUTPUT")]
output: Option<String>,
#[arg(long)]
raw_line: Vec<String>,
#[arg(long, number_of_values = 2, value_names = ["MODULE_NAME", "RAW_LINE"])]
module_raw_line: Vec<String>,
#[arg(long, help = rust_target_help())]
rust_target: Option<RustTarget>,
#[arg(long, value_name = "EDITION", help = rust_edition_help())]
rust_edition: Option<RustEdition>,
#[arg(long)]
use_core: bool,
#[arg(long)]
conservative_inline_namespaces: bool,
#[arg(long, value_name = "REGEX")]
allowlist_function: Vec<String>,
#[arg(long)]
generate_inline_functions: bool,
#[arg(long, value_name = "REGEX")]
allowlist_type: Vec<String>,
#[arg(long, value_name = "REGEX")]
allowlist_var: Vec<String>,
#[arg(long, value_name = "PATH")]
allowlist_file: Vec<String>,
#[arg(long, value_name = "REGEX")]
allowlist_item: Vec<String>,
#[arg(long)]
verbose: bool,
#[arg(long)]
dump_preprocessed_input: bool,
#[arg(long)]
no_record_matches: bool,
#[arg(long = "no-size_t-is-usize")]
no_size_t_is_usize: bool,
#[arg(long)]
no_rustfmt_bindings: bool,
#[arg(
long,
value_name = "FORMATTER",
conflicts_with = "no_rustfmt_bindings"
)]
formatter: Option<Formatter>,
#[arg(long, value_name = "PATH", conflicts_with = "no_rustfmt_bindings", value_parser=parse_rustfmt_config_path)]
rustfmt_configuration_file: Option<PathBuf>,
#[arg(long, value_name = "REGEX")]
no_partialeq: Vec<String>,
#[arg(long, value_name = "REGEX")]
no_copy: Vec<String>,
#[arg(long, value_name = "REGEX")]
no_debug: Vec<String>,
#[arg(long, value_name = "REGEX")]
no_default: Vec<String>,
#[arg(long, value_name = "REGEX")]
no_hash: Vec<String>,
#[arg(long, value_name = "REGEX")]
must_use_type: Vec<String>,
#[arg(long)]
enable_function_attribute_detection: bool,
#[arg(long)]
use_array_pointers_in_arguments: bool,
#[arg(long, value_name = "NAME")]
wasm_import_module_name: Option<String>,
#[arg(long, value_name = "ATTRS")]
extern_fn_block_attrs: Vec<String>,
#[arg(long, value_name = "NAME")]
dynamic_loading: Option<String>,
#[arg(long)]
dynamic_link_require_all: bool,
#[arg(long)]
prefix_link_name: Option<String>,
#[arg(long)]
respect_cxx_access_specs: bool,
#[arg(long)]
translate_enum_integer_types: bool,
#[arg(long)]
c_naming: bool,
#[arg(long)]
explicit_padding: bool,
#[arg(long)]
use_specific_virtual_function_receiver: bool,
#[arg(long)]
use_distinct_char16_t: bool,
#[arg(long)]
represent_cxx_operators: bool,
#[arg(long)]
vtable_generation: bool,
#[arg(long)]
sort_semantically: bool,
#[arg(long)]
merge_extern_blocks: bool,
#[arg(long, value_name = "OVERRIDE", value_parser = parse_abi_override)]
override_abi: Vec<(Abi, String)>,
#[arg(long)]
wrap_unsafe_ops: bool,
#[arg(long)]
clang_macro_fallback: bool,
#[arg(long)]
clang_macro_fallback_build_dir: Option<PathBuf>,
#[arg(long)]
flexarray_dst: bool,
#[arg(long, value_name = "CUSTOM", value_parser = parse_custom_derive)]
with_derive_custom: Vec<(Vec<String>, String)>,
#[arg(long, value_name = "CUSTOM", value_parser = parse_custom_derive)]
with_derive_custom_struct: Vec<(Vec<String>, String)>,
#[arg(long, value_name = "CUSTOM", value_parser = parse_custom_derive)]
with_derive_custom_enum: Vec<(Vec<String>, String)>,
#[arg(long, value_name = "CUSTOM", value_parser = parse_custom_derive)]
with_derive_custom_union: Vec<(Vec<String>, String)>,
#[arg(long, value_name = "CUSTOM", value_parser = parse_custom_attribute)]
with_attribute_custom: Vec<(Vec<String>, String)>,
#[arg(long, value_name = "CUSTOM", value_parser = parse_custom_attribute)]
with_attribute_custom_struct: Vec<(Vec<String>, String)>,
#[arg(long, value_name = "CUSTOM", value_parser = parse_custom_attribute)]
with_attribute_custom_enum: Vec<(Vec<String>, String)>,
#[arg(long, value_name = "CUSTOM", value_parser = parse_custom_attribute)]
with_attribute_custom_union: Vec<(Vec<String>, String)>,
#[arg(long)]
wrap_static_fns: bool,
#[arg(long, value_name = "PATH")]
wrap_static_fns_path: Option<PathBuf>,
#[arg(long, value_name = "SUFFIX")]
wrap_static_fns_suffix: Option<String>,
#[arg(long, value_name = "VISIBILITY")]
default_visibility: Option<FieldVisibilityKind>,
#[arg(long)]
generate_deleted_functions: bool,
#[arg(long)]
generate_pure_virtual_functions: bool,
#[arg(long)]
generate_private_functions: bool,
#[arg(long, value_name = "SPEC", value_parser = parse_field_attr)]
field_attr: Vec<(String, String, String)>,
#[cfg(feature = "experimental")]
#[arg(long, requires = "experimental")]
emit_diagnostics: bool,
#[arg(long, value_name = "SHELL")]
generate_shell_completions: Option<clap_complete::Shell>,
#[arg(long)]
experimental: bool,
#[arg(short = 'V', long)]
version: bool,
clang_args: Vec<String>,
}
pub fn builder_from_flags<I>(
args: I,
) -> Result<(Builder, Box<dyn io::Write>, bool), io::Error>
where
I: Iterator<Item = String>,
{
let command = BindgenCommand::parse_from(args);
let BindgenCommand {
header,
depfile,
default_enum_style,
bitfield_enum,
newtype_enum,
newtype_global_enum,
rustified_enum,
rustified_non_exhaustive_enum,
constified_enum,
constified_enum_module,
default_macro_constant_type,
default_alias_style,
normal_alias,
new_type_alias,
new_type_alias_deref,
default_non_copy_union_style,
bindgen_wrapper_union,
manually_drop_union,
blocklist_type,
blocklist_function,
blocklist_item,
blocklist_file,
blocklist_var,
no_layout_tests,
no_derive_copy,
no_derive_debug,
no_derive_default,
impl_debug,
impl_partialeq,
with_derive_default,
with_derive_hash,
with_derive_partialeq,
with_derive_partialord,
with_derive_eq,
with_derive_ord,
no_doc_comments,
no_recursive_allowlist,
objc_extern_crate,
nonnull_references,
generate_block,
generate_cstr,
block_extern_crate,
distrust_clang_mangling,
builtins,
ctypes_prefix,
anon_fields_prefix,
time_phases,
emit_clang_ast,
emit_ir,
emit_ir_graphviz,
enable_cxx_namespaces,
disable_name_namespacing,
disable_nested_struct_naming,
disable_untagged_union,
disable_header_comment,
ignore_functions,
generate,
ignore_methods,
no_convert_floats,
no_prepend_enum_name,
no_include_path_detection,
fit_macro_constant_types,
opaque_type,
output,
raw_line,
module_raw_line,
rust_target,
rust_edition,
use_core,
conservative_inline_namespaces,
allowlist_function,
generate_inline_functions,
allowlist_type,
allowlist_var,
allowlist_file,
allowlist_item,
verbose,
dump_preprocessed_input,
no_record_matches,
no_size_t_is_usize,
no_rustfmt_bindings,
formatter,
rustfmt_configuration_file,
no_partialeq,
no_copy,
no_debug,
no_default,
no_hash,
must_use_type,
enable_function_attribute_detection,
use_array_pointers_in_arguments,
wasm_import_module_name,
extern_fn_block_attrs,
dynamic_loading,
dynamic_link_require_all,
prefix_link_name,
respect_cxx_access_specs,
translate_enum_integer_types,
c_naming,
explicit_padding,
use_specific_virtual_function_receiver,
use_distinct_char16_t,
represent_cxx_operators,
vtable_generation,
sort_semantically,
merge_extern_blocks,
override_abi,
wrap_unsafe_ops,
clang_macro_fallback,
clang_macro_fallback_build_dir,
flexarray_dst,
with_derive_custom,
with_derive_custom_struct,
with_derive_custom_enum,
with_derive_custom_union,
with_attribute_custom,
with_attribute_custom_struct,
with_attribute_custom_enum,
with_attribute_custom_union,
wrap_static_fns,
wrap_static_fns_path,
wrap_static_fns_suffix,
default_visibility,
generate_deleted_functions,
generate_pure_virtual_functions,
generate_private_functions,
field_attr,
#[cfg(feature = "experimental")]
emit_diagnostics,
generate_shell_completions,
experimental: _,
version,
clang_args,
} = command;
if let Some(shell) = generate_shell_completions {
clap_complete::generate(
shell,
&mut BindgenCommand::command(),
"bindgen",
&mut io::stdout(),
);
exit(0)
}
if version {
println!(
"bindgen {}",
option_env!("CARGO_PKG_VERSION").unwrap_or("unknown")
);
if verbose {
println!("Clang: {}", crate::clang_version().full);
}
exit(0)
}
if header.is_none() {
return Err(io::Error::new(io::ErrorKind::Other, "Header not found"));
}
let mut builder = builder();
#[derive(Debug)]
struct PrefixLinkNameCallback {
prefix: String,
}
impl ParseCallbacks for PrefixLinkNameCallback {
fn generated_link_name_override(
&self,
item_info: ItemInfo<'_>,
) -> Option<String> {
let mut prefix = self.prefix.clone();
prefix.push_str(item_info.name);
Some(prefix)
}
}
#[derive(Debug)]
struct CustomDeriveCallback {
derives: Vec<String>,
kind: Option<TypeKind>,
regex_set: RegexSet,
}
impl ParseCallbacks for CustomDeriveCallback {
fn cli_args(&self) -> Vec<String> {
let mut args = vec![];
let flag = match &self.kind {
None => "--with-derive-custom",
Some(TypeKind::Struct) => "--with-derive-custom-struct",
Some(TypeKind::Enum) => "--with-derive-custom-enum",
Some(TypeKind::Union) => "--with-derive-custom-union",
};
let derives = self.derives.join(",");
for item in self.regex_set.get_items() {
args.extend_from_slice(&[
flag.to_owned(),
format!("{item}={derives}"),
]);
}
args
}
fn add_derives(&self, info: &DeriveInfo<'_>) -> Vec<String> {
if self.kind.map_or(true, |kind| kind == info.kind) &&
self.regex_set.matches(info.name)
{
return self.derives.clone();
}
vec![]
}
}
#[derive(Debug)]
struct CustomAttributeCallback {
attributes: Vec<String>,
kind: Option<TypeKind>,
regex_set: RegexSet,
}
impl ParseCallbacks for CustomAttributeCallback {
fn cli_args(&self) -> Vec<String> {
let mut args = vec![];
let flag = match &self.kind {
None => "--with-attribute-custom",
Some(TypeKind::Struct) => "--with-attribute-custom-struct",
Some(TypeKind::Enum) => "--with-attribute-custom-enum",
Some(TypeKind::Union) => "--with-attribute-custom-union",
};
let attributes = self.attributes.join(",");
for item in self.regex_set.get_items() {
args.extend_from_slice(&[
flag.to_owned(),
format!("{item}={attributes}"),
]);
}
args
}
fn add_attributes(&self, info: &AttributeInfo<'_>) -> Vec<String> {
if self.kind.map_or(true, |kind| kind == info.kind) &&
self.regex_set.matches(info.name)
{
return self.attributes.clone();
}
vec![]
}
}
macro_rules! apply_args {
($builder:ident {}) => { $builder };
($builder:ident {$arg:ident => $function:expr, $($token:tt)*}) => {
{
$builder = CliArg::apply($arg, $builder, $function);
apply_args!($builder {$($token)*})
}
};
($builder:ident {$arg:ident, $($token:tt)*}) => {
{
$builder = CliArg::apply($arg, $builder, Builder::$arg);
apply_args!($builder {$($token)*})
}
}
}
builder = apply_args!(
builder {
header,
rust_target,
rust_edition,
default_enum_style,
bitfield_enum,
newtype_enum,
newtype_global_enum,
rustified_enum,
rustified_non_exhaustive_enum,
constified_enum,
constified_enum_module,
default_macro_constant_type,
default_alias_style,
normal_alias => Builder::type_alias,
new_type_alias,
new_type_alias_deref,
default_non_copy_union_style,
bindgen_wrapper_union,
manually_drop_union,
blocklist_type,
blocklist_function,
blocklist_item,
blocklist_file,
blocklist_var,
builtins => |b, _| b.emit_builtins(),
no_layout_tests => |b, _| b.layout_tests(false),
no_derive_copy => |b, _| b.derive_copy(false),
no_derive_debug => |b, _| b.derive_debug(false),
impl_debug,
impl_partialeq,
with_derive_default => Builder::derive_default,
with_derive_hash => Builder::derive_hash,
with_derive_partialeq => Builder::derive_partialeq,
with_derive_partialord => Builder::derive_partialord,
with_derive_eq => Builder::derive_eq,
with_derive_ord => Builder::derive_ord,
no_derive_default => |b, _| b.derive_default(false),
no_prepend_enum_name => |b, _| b.prepend_enum_name(false),
no_include_path_detection => |b, _| b.detect_include_paths(false),
fit_macro_constant_types => Builder::fit_macro_constants,
time_phases,
use_array_pointers_in_arguments => Builder::array_pointers_in_arguments,
wasm_import_module_name,
extern_fn_block_attrs => Builder::extern_fn_block_attrs,
ctypes_prefix,
anon_fields_prefix,
generate => Builder::with_codegen_config,
emit_clang_ast => |b, _| b.emit_clang_ast(),
emit_ir => |b, _| b.emit_ir(),
emit_ir_graphviz,
enable_cxx_namespaces => |b, _| b.enable_cxx_namespaces(),
enable_function_attribute_detection => |b, _| b.enable_function_attribute_detection(),
disable_name_namespacing => |b, _| b.disable_name_namespacing(),
disable_nested_struct_naming => |b, _| b.disable_nested_struct_naming(),
disable_untagged_union => |b, _| b.disable_untagged_union(),
disable_header_comment => |b, _| b.disable_header_comment(),
ignore_functions => |b, _| b.ignore_functions(),
ignore_methods => |b, _| b.ignore_methods(),
no_convert_floats => |b, _| b.no_convert_floats(),
no_doc_comments => |b, _| b.generate_comments(false),
no_recursive_allowlist => |b, _| b.allowlist_recursively(false),
objc_extern_crate,
nonnull_references => |b, _| b.generate_cxx_nonnull_references(true),
generate_block,
generate_cstr,
block_extern_crate,
opaque_type,
raw_line,
use_core => |b, _| b.use_core(),
distrust_clang_mangling => |b, _| b.trust_clang_mangling(false),
conservative_inline_namespaces => |b, _| b.conservative_inline_namespaces(),
generate_inline_functions,
allowlist_function,
allowlist_type,
allowlist_var,
allowlist_file,
allowlist_item,
clang_args => Builder::clang_arg,
no_record_matches => |b, _| b.record_matches(false),
no_size_t_is_usize => |b, _| b.size_t_is_usize(false),
no_rustfmt_bindings => |b, _| b.formatter(Formatter::None),
formatter,
no_partialeq,
no_copy,
no_debug,
no_default,
no_hash,
must_use_type,
dynamic_loading => Builder::dynamic_library_name,
dynamic_link_require_all,
prefix_link_name => |b, prefix| b.parse_callbacks(Box::new(PrefixLinkNameCallback { prefix })),
respect_cxx_access_specs,
translate_enum_integer_types,
c_naming,
explicit_padding,
use_specific_virtual_function_receiver,
use_distinct_char16_t,
represent_cxx_operators,
vtable_generation,
sort_semantically,
merge_extern_blocks,
override_abi => |b, (abi, regex)| b.override_abi(abi, regex),
wrap_unsafe_ops,
clang_macro_fallback => |b, _| b.clang_macro_fallback(),
clang_macro_fallback_build_dir,
flexarray_dst,
wrap_static_fns,
wrap_static_fns_path,
wrap_static_fns_suffix,
default_visibility,
generate_deleted_functions,
generate_pure_virtual_functions,
generate_private_functions,
field_attr => |b, (type_name, field_name, attr)| b.field_attribute(type_name, field_name, attr),
}
);
let mut values = module_raw_line.into_iter();
while let Some(module) = values.next() {
let line = values.next().unwrap();
builder = builder.module_raw_line(module, line);
}
let output = if let Some(path) = &output {
let file = File::create(path)?;
if let Some(depfile) = depfile {
builder = builder.depfile(path, depfile);
}
Box::new(io::BufWriter::new(file)) as Box<dyn io::Write>
} else {
if let Some(depfile) = depfile {
builder = builder.depfile("-", depfile);
}
Box::new(io::BufWriter::new(io::stdout())) as Box<dyn io::Write>
};
if dump_preprocessed_input {
builder.dump_preprocessed_input()?;
}
if let Some(path) = rustfmt_configuration_file {
builder = builder.rustfmt_configuration_file(Some(path));
}
for (custom_derives, kind, _name) in [
(with_derive_custom, None, "--with-derive-custom"),
(
with_derive_custom_struct,
Some(TypeKind::Struct),
"--with-derive-custom-struct",
),
(
with_derive_custom_enum,
Some(TypeKind::Enum),
"--with-derive-custom-enum",
),
(
with_derive_custom_union,
Some(TypeKind::Union),
"--with-derive-custom-union",
),
] {
#[cfg(feature = "experimental")]
let name = emit_diagnostics.then_some(_name);
for (derives, regex) in custom_derives {
let mut regex_set = RegexSet::default();
regex_set.insert(regex);
#[cfg(feature = "experimental")]
regex_set.build_with_diagnostics(false, name);
#[cfg(not(feature = "experimental"))]
regex_set.build(false);
builder = builder.parse_callbacks(Box::new(CustomDeriveCallback {
derives,
kind,
regex_set,
}));
}
}
for (custom_attributes, kind, _name) in [
(with_attribute_custom, None, "--with-attribute-custom"),
(
with_attribute_custom_struct,
Some(TypeKind::Struct),
"--with-attribute-custom-struct",
),
(
with_attribute_custom_enum,
Some(TypeKind::Enum),
"--with-attribute-custom-enum",
),
(
with_attribute_custom_union,
Some(TypeKind::Union),
"--with-attribute-custom-union",
),
] {
#[cfg(feature = "experimental")]
let name = emit_diagnostics.then_some(_name);
for (attributes, regex) in custom_attributes {
let mut regex_set = RegexSet::default();
regex_set.insert(regex);
#[cfg(feature = "experimental")]
regex_set.build_with_diagnostics(false, name);
#[cfg(not(feature = "experimental"))]
regex_set.build(false);
builder =
builder.parse_callbacks(Box::new(CustomAttributeCallback {
attributes,
kind,
regex_set,
}));
}
}
#[cfg(feature = "experimental")]
if emit_diagnostics {
builder = builder.emit_diagnostics();
}
Ok((builder, output, verbose))
}
trait CliArg {
type Value;
fn apply(
self,
builder: Builder,
f: impl Fn(Builder, Self::Value) -> Builder,
) -> Builder;
}
impl CliArg for bool {
type Value = bool;
fn apply(
self,
mut builder: Builder,
f: impl Fn(Builder, Self::Value) -> Builder,
) -> Builder {
if self {
builder = f(builder, self);
}
builder
}
}
impl<T> CliArg for Option<T> {
type Value = T;
fn apply(
self,
mut builder: Builder,
f: impl Fn(Builder, Self::Value) -> Builder,
) -> Builder {
if let Some(value) = self {
builder = f(builder, value);
}
builder
}
}
impl<T> CliArg for Vec<T> {
type Value = T;
fn apply(
self,
mut builder: Builder,
f: impl Fn(Builder, Self::Value) -> Builder,
) -> Builder {
for value in self {
builder = f(builder, value);
}
builder
}
}