Skip to content

Commit b6f4f24

Browse files
committed
Don't require a Box wrapper on Bindings::write()
The function in question doesn't store the `dyn Write` trait object anywhere, allowing us to pass a plain `&mut dyn Write` (which is also implemented for `&mut Box<dyn Write>` allowing the existing CLI parser to operate normally). This in turn no longer requires users of `bindgen` to wrap their `&mut File` or `&mut Vec<u8>` in a moved `Box` just to be able to give temporary mutable access to the `write() function`.
1 parent 5813198 commit b6f4f24

File tree

4 files changed

+27
-41
lines changed

4 files changed

+27
-41
lines changed

bindgen-cli/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub fn main() {
2929
env_logger::init();
3030

3131
match builder_from_flags(env::args()) {
32-
Ok((builder, output, verbose)) => {
32+
Ok((builder, mut output, verbose)) => {
3333
#[cfg(feature = "logging")]
3434
clang_version_check();
3535

@@ -50,7 +50,7 @@ pub fn main() {
5050

5151
let _ = std::panic::take_hook();
5252

53-
bindings.write(output).expect("Unable to write output");
53+
bindings.write(&mut output).expect("Unable to write output");
5454
}
5555
Err(error) => {
5656
eprintln!("{error}");

bindgen-tests/tests/parse_callbacks/add_derives_callback/mod.rs

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,11 @@ mod tests {
1919
}
2020
}
2121

22-
struct WriteAdapter<'a>(&'a mut Vec<u8>);
23-
24-
impl std::io::Write for WriteAdapter<'_> {
25-
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
26-
self.0.extend_from_slice(buf);
27-
Ok(buf.len())
28-
}
29-
fn flush(&mut self) -> std::io::Result<()> {
30-
Ok(())
31-
}
32-
}
33-
3422
fn write_bindings_to_string(bindings: &Bindings) -> String {
3523
let mut output = Vec::<u8>::new();
36-
bindings
37-
.write(Box::new(WriteAdapter(&mut output)))
38-
.unwrap_or_else(|e| {
39-
panic!("Failed to write generated bindings: {e}")
40-
});
24+
bindings.write(&mut output).unwrap_or_else(|e| {
25+
panic!("Failed to write generated bindings: {e}")
26+
});
4127
String::from_utf8(output).unwrap_or_else(|e| {
4228
panic!("Failed to convert generated bindings to string: {e}")
4329
})
@@ -74,8 +60,8 @@ mod tests {
7460
let output = write_bindings_to_string(&bindings);
7561
let output_without_spaces = output.replace(' ', "");
7662
assert!(
77-
output_without_spaces.contains("#[derive(Debug)]") &&
78-
!output_without_spaces.contains("#[derive(Debug,Debug)]"),
63+
output_without_spaces.contains("#[derive(Debug)]")
64+
&& !output_without_spaces.contains("#[derive(Debug,Debug)]"),
7965
"Unexpected bindgen output:\n{}",
8066
output.as_str()
8167
);

bindgen/lib.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,10 @@ const DEFAULT_NON_EXTERN_FNS_SUFFIX: &str = "__extern";
8787

8888
fn file_is_cpp(name_file: &str) -> bool {
8989
Path::new(name_file).extension().is_some_and(|ext| {
90-
ext.eq_ignore_ascii_case("hpp") ||
91-
ext.eq_ignore_ascii_case("hxx") ||
92-
ext.eq_ignore_ascii_case("hh") ||
93-
ext.eq_ignore_ascii_case("h++")
90+
ext.eq_ignore_ascii_case("hpp")
91+
|| ext.eq_ignore_ascii_case("hxx")
92+
|| ext.eq_ignore_ascii_case("hh")
93+
|| ext.eq_ignore_ascii_case("h++")
9494
})
9595
}
9696

@@ -347,10 +347,10 @@ impl Builder {
347347
.clang_args
348348
.iter()
349349
.filter(|arg| {
350-
!arg.starts_with("-MMD") &&
351-
!arg.starts_with("-MD") &&
352-
!arg.starts_with("--write-user-dependencies") &&
353-
!arg.starts_with("--user-dependencies")
350+
!arg.starts_with("-MMD")
351+
&& !arg.starts_with("-MD")
352+
&& !arg.starts_with("--write-user-dependencies")
353+
&& !arg.starts_with("--user-dependencies")
354354
})
355355
.cloned()
356356
.collect::<Vec<_>>();
@@ -819,8 +819,8 @@ impl Bindings {
819819
return false;
820820
}
821821

822-
if arg.starts_with("-I") ||
823-
arg.starts_with("--include-directory=")
822+
if arg.starts_with("-I")
823+
|| arg.starts_with("--include-directory=")
824824
{
825825
return false;
826826
}
@@ -845,8 +845,8 @@ impl Bindings {
845845
debug!("Found clang: {clang:?}");
846846

847847
// Whether we are working with C or C++ inputs.
848-
let is_cpp = args_are_cpp(&options.clang_args) ||
849-
options.input_headers.iter().any(|h| file_is_cpp(h));
848+
let is_cpp = args_are_cpp(&options.clang_args)
849+
|| options.input_headers.iter().any(|h| file_is_cpp(h));
850850

851851
let search_paths = if is_cpp {
852852
clang.cpp_search_paths
@@ -927,17 +927,17 @@ impl Bindings {
927927

928928
/// Write these bindings as source text to a file.
929929
pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
930-
let file = OpenOptions::new()
930+
let mut file = OpenOptions::new()
931931
.write(true)
932932
.truncate(true)
933933
.create(true)
934934
.open(path.as_ref())?;
935-
self.write(Box::new(file))?;
935+
self.write(&mut file)?;
936936
Ok(())
937937
}
938938

939939
/// Write these bindings as source text to the given `Write`able.
940-
pub fn write<'a>(&self, mut writer: Box<dyn Write + 'a>) -> io::Result<()> {
940+
pub fn write(&self, writer: &mut dyn Write) -> io::Result<()> {
941941
const NL: &str = if cfg!(windows) { "\r\n" } else { "\n" };
942942

943943
if !self.options.disable_header_comment {
@@ -1090,7 +1090,7 @@ fn rustfmt_non_fatal_error_diagnostic(msg: &str, _options: &BindgenOptions) {
10901090
impl std::fmt::Display for Bindings {
10911091
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10921092
let mut bytes = vec![];
1093-
self.write(Box::new(&mut bytes) as Box<dyn Write>)
1093+
self.write(&mut bytes)
10941094
.expect("writing to a vec cannot fail");
10951095
f.write_str(
10961096
std::str::from_utf8(&bytes)

bindgen/options/cli.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -797,8 +797,8 @@ where
797797
}
798798

799799
fn add_derives(&self, info: &DeriveInfo<'_>) -> Vec<String> {
800-
if self.kind.map_or(true, |kind| kind == info.kind) &&
801-
self.regex_set.matches(info.name)
800+
if self.kind.map_or(true, |kind| kind == info.kind)
801+
&& self.regex_set.matches(info.name)
802802
{
803803
return self.derives.clone();
804804
}
@@ -837,8 +837,8 @@ where
837837
}
838838

839839
fn add_attributes(&self, info: &AttributeInfo<'_>) -> Vec<String> {
840-
if self.kind.map_or(true, |kind| kind == info.kind) &&
841-
self.regex_set.matches(info.name)
840+
if self.kind.map_or(true, |kind| kind == info.kind)
841+
&& self.regex_set.matches(info.name)
842842
{
843843
return self.attributes.clone();
844844
}

0 commit comments

Comments
 (0)