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::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)
}
}
}

View File

@ -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)
}
}
}
}
}

View File

@ -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>);
@ -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 {
@ -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;
}
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
};
func(&mut measurer);
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 {