Skip to content

Commit

Permalink
Avoid doing double the work when measuring.
Browse files Browse the repository at this point in the history
  • Loading branch information
emilio committed Nov 10, 2022
1 parent e0eaecf commit d8660bb
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 39 deletions.
10 changes: 4 additions & 6 deletions src/bindgen/cdecl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,13 +331,11 @@ impl CDecl {
Layout::Vertical => write_vertical(out, config, args),
Layout::Horizontal => write_horizontal(out, config, args),
Layout::Auto => {
if out.line_length_for_align()
+ out.measure(|out| write_horizontal(out, config, args))
> config.line_length
{
if !out.try_write(
|out| write_horizontal(out, config, args),
config.line_length,
) {
write_vertical(out, config, args)
} else {
write_horizontal(out, config, args)
}
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/bindgen/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,14 +304,14 @@ impl Source for Function {
condition.write_after(config, out);
}

let option_1 = out.measure(|out| write_1(self, config, out));

if (config.function.args == Layout::Auto && option_1 <= config.line_length)
|| config.function.args == Layout::Horizontal
{
write_1(self, config, out);
} else {
write_2(self, config, out);
match config.function.args {
Layout::Horizontal => write_1(self, config, out),
Layout::Vertical => write_2(self, config, out),
Layout::Auto => {
if !out.try_write(|out| write_1(self, config, out), config.line_length) {
write_2(self, config, out)
}
}
}
}
}
Expand Down
54 changes: 29 additions & 25 deletions src/bindgen/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,6 @@ pub enum ListType<'a> {
Cap(&'a str),
}

/// An empty file used for creating a null source writer and measuring line
/// metrics for various code layouts.
pub struct NullFile;
impl Write for NullFile {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}

/// A utility wrapper to write unbuffered data and correctly adjust positions.
struct InnerWriter<'a, 'b: 'a, F: 'a + Write>(&'a mut SourceWriter<'b, F>);

Expand Down Expand Up @@ -66,7 +54,7 @@ pub struct SourceWriter<'a, F: Write> {
max_line_length: usize,
}

pub type MeasureWriter<'a> = SourceWriter<'a, NullFile>;
pub type MeasureWriter<'a> = SourceWriter<'a, &'a mut Vec<u8>>;

impl<'a, F: Write> SourceWriter<'a, F> {
pub fn new(out: F, bindings: &'a Bindings) -> Self {
Expand All @@ -87,23 +75,39 @@ impl<'a, F: Write> SourceWriter<'a, F> {

/// Takes a function that writes source and returns the maximum line length
/// written.
pub fn measure<T>(&self, func: T) -> usize
pub fn try_write<T>(&mut self, func: T, max_line_length: usize) -> bool
where
T: Fn(&mut MeasureWriter),
{
let mut measurer = SourceWriter {
out: NullFile,
bindings: self.bindings,
spaces: self.spaces.clone(),
line_started: self.line_started,
line_length: self.line_length,
line_number: self.line_number,
max_line_length: self.line_length,
};
if self.line_length > max_line_length {
return false;
}

func(&mut measurer);
let mut buffer = Vec::new();
let line_length = {
let mut measurer = SourceWriter {
out: &mut buffer,
bindings: self.bindings,
spaces: self.spaces.clone(),
line_started: self.line_started,
line_length: self.line_length,
line_number: self.line_number,
max_line_length: self.line_length,
};

func(&mut measurer);

measurer.max_line_length
};

measurer.max_line_length
if line_length > max_line_length {
return false;
}
// We don't want the extra alignment, it's already accounted for by the
// measurer.
self.line_started = true;
InnerWriter(self).write_all(&buffer).unwrap();
true
}

fn spaces(&self) -> usize {
Expand Down

0 comments on commit d8660bb

Please sign in to comment.