diff --git a/src/bindgen/cdecl.rs b/src/bindgen/cdecl.rs index c0afdc249..7e2ad4e10 100644 --- a/src/bindgen/cdecl.rs +++ b/src/bindgen/cdecl.rs @@ -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) } } } diff --git a/src/bindgen/ir/function.rs b/src/bindgen/ir/function.rs index 27df2a0b8..da0920767 100644 --- a/src/bindgen/ir/function.rs +++ b/src/bindgen/ir/function.rs @@ -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) + } + } } } } diff --git a/src/bindgen/writer.rs b/src/bindgen/writer.rs index 3291af911..a5336e5ed 100644 --- a/src/bindgen/writer.rs +++ b/src/bindgen/writer.rs @@ -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 { - 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>); @@ -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>; impl<'a, F: Write> SourceWriter<'a, F> { pub fn new(out: F, bindings: &'a Bindings) -> Self { @@ -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(&self, func: T) -> usize + pub fn try_write(&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 {