Avoid doing double the work when measuring.

This commit is contained in:
Emilio Cobos Álvarez 2022-11-10 14:18:43 +01:00
parent e0eaecfdf7
commit d8660bb01f
No known key found for this signature in database
GPG Key ID: E1152D0994E4BF8A
3 changed files with 41 additions and 39 deletions

View File

@ -331,13 +331,11 @@ impl CDecl {
Layout::Vertical => write_vertical(out, config, args), Layout::Vertical => write_vertical(out, config, args),
Layout::Horizontal => write_horizontal(out, config, args), Layout::Horizontal => write_horizontal(out, config, args),
Layout::Auto => { Layout::Auto => {
if out.line_length_for_align() if !out.try_write(
+ out.measure(|out| write_horizontal(out, config, args)) |out| write_horizontal(out, config, args),
> config.line_length config.line_length,
{ ) {
write_vertical(out, config, args) write_vertical(out, config, args)
} else {
write_horizontal(out, config, args)
} }
} }
} }

View File

@ -304,14 +304,14 @@ impl Source for Function {
condition.write_after(config, out); condition.write_after(config, out);
} }
let option_1 = out.measure(|out| write_1(self, config, out)); match config.function.args {
Layout::Horizontal => write_1(self, config, out),
if (config.function.args == Layout::Auto && option_1 <= config.line_length) Layout::Vertical => write_2(self, config, out),
|| config.function.args == Layout::Horizontal Layout::Auto => {
{ if !out.try_write(|out| write_1(self, config, out), config.line_length) {
write_1(self, config, out); write_2(self, config, out)
} else { }
write_2(self, config, out); }
} }
} }
} }

View File

@ -17,18 +17,6 @@ pub enum ListType<'a> {
Cap(&'a str), 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. /// A utility wrapper to write unbuffered data and correctly adjust positions.
struct InnerWriter<'a, 'b: 'a, F: 'a + Write>(&'a mut SourceWriter<'b, F>); 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, 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> { impl<'a, F: Write> SourceWriter<'a, F> {
pub fn new(out: F, bindings: &'a Bindings) -> Self { 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 /// Takes a function that writes source and returns the maximum line length
/// written. /// written.
pub fn measure<T>(&self, func: T) -> usize pub fn try_write<T>(&mut self, func: T, max_line_length: usize) -> bool
where where
T: Fn(&mut MeasureWriter), T: Fn(&mut MeasureWriter),
{ {
let mut measurer = SourceWriter { if self.line_length > max_line_length {
out: NullFile, return false;
bindings: self.bindings, }
spaces: self.spaces.clone(),
line_started: self.line_started, let mut buffer = Vec::new();
line_length: self.line_length, let line_length = {
line_number: self.line_number, let mut measurer = SourceWriter {
max_line_length: self.line_length, 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
}; };
func(&mut measurer); if line_length > max_line_length {
return false;
measurer.max_line_length }
// 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 { fn spaces(&self) -> usize {