From e0e7ac37b29861911c2817da51c09764a384973b Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 24 Nov 2017 09:56:19 +0100 Subject: Make fmt::DebugList and friends forward formatting parameters For example, formatting slice of integers with `{:04?}` should zero-pad each integer. --- src/libcore/fmt/builders.rs | 86 ++++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 28 deletions(-) (limited to 'src/libcore/fmt') diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index 60b9eeb1283..f213578c127 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -22,6 +22,25 @@ impl<'a, 'b: 'a> PadAdapter<'a, 'b> { on_newline: false, } } + + fn as_formatter(&mut self) -> fmt::Formatter { + fmt::Formatter { + // These only exist in the struct for the `Formatter::run` method, + // which won’t be used. + curarg: self.fmt.curarg.clone(), + args: self.fmt.args, + + // We want to preserve these + flags: self.fmt.flags, + fill: self.fmt.fill, + align: self.fmt.align, + width: self.fmt.width, + precision: self.fmt.precision, + + // And change this + buf: self, + } + } } impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> { @@ -112,11 +131,16 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { }; if self.is_pretty() { + use fmt::Write; let mut writer = PadAdapter::new(self.fmt); - fmt::write(&mut writer, - format_args!("{}\n{}: {:#?}", prefix, name, value)) + writer.write_str(prefix)?; + writer.write_str("\n")?; + writer.write_str(name)?; + writer.write_str(": ")?; + value.fmt(&mut writer.as_formatter()) } else { - write!(self.fmt, "{} {}: {:?}", prefix, name, value) + write!(self.fmt, "{} {}: ", prefix, name)?; + value.fmt(self.fmt) } }); @@ -204,10 +228,15 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { }; if self.is_pretty() { + use fmt::Write; let mut writer = PadAdapter::new(self.fmt); - fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, value)) + writer.write_str(prefix)?; + writer.write_str("\n")?; + value.fmt(&mut writer.as_formatter()) } else { - write!(self.fmt, "{}{}{:?}", prefix, space, value) + self.fmt.write_str(prefix)?; + self.fmt.write_str(space)?; + value.fmt(self.fmt) } }); @@ -247,20 +276,19 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { fn entry(&mut self, entry: &fmt::Debug) { self.result = self.result.and_then(|_| { if self.is_pretty() { + use fmt::Write; let mut writer = PadAdapter::new(self.fmt); - let prefix = if self.has_fields { - "," + writer.write_str(if self.has_fields { + ",\n" } else { - "" - }; - fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, entry)) + "\n" + })?; + entry.fmt(&mut writer.as_formatter()) } else { - let prefix = if self.has_fields { - ", " - } else { - "" - }; - write!(self.fmt, "{}{:?}", prefix, entry) + if self.has_fields { + self.fmt.write_str(", ")? + } + entry.fmt(self.fmt) } }); @@ -472,21 +500,23 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { pub fn entry(&mut self, key: &fmt::Debug, value: &fmt::Debug) -> &mut DebugMap<'a, 'b> { self.result = self.result.and_then(|_| { if self.is_pretty() { + use fmt::Write; let mut writer = PadAdapter::new(self.fmt); - let prefix = if self.has_fields { - "," + writer.write_str(if self.has_fields { + ",\n" } else { - "" - }; - fmt::write(&mut writer, - format_args!("{}\n{:#?}: {:#?}", prefix, key, value)) + "\n" + })?; + key.fmt(&mut writer.as_formatter())?; + writer.write_str(": ")?; + value.fmt(&mut writer.as_formatter()) } else { - let prefix = if self.has_fields { - ", " - } else { - "" - }; - write!(self.fmt, "{}{:?}: {:?}", prefix, key, value) + if self.has_fields { + self.fmt.write_str(", ")? + } + key.fmt(self.fmt)?; + self.fmt.write_str(": ")?; + value.fmt(self.fmt) } }); -- cgit 1.4.1-3-g733a5 From bf087895102f1ab275a7ceed9f789dcfb7e172f3 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 27 Nov 2017 14:37:40 +0100 Subject: Keep access to private Formatter fields in Formatter methods --- src/libcore/fmt/builders.rs | 71 ++++++++++++++++++--------------------------- src/libcore/fmt/mod.rs | 21 ++++++++++++++ 2 files changed, 49 insertions(+), 43 deletions(-) (limited to 'src/libcore/fmt') diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index f213578c127..a1f4c6995da 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -10,44 +10,29 @@ use fmt; -struct PadAdapter<'a, 'b: 'a> { - fmt: &'a mut fmt::Formatter<'b>, +struct PadAdapter<'a> { + buf: &'a mut (fmt::Write + 'a), on_newline: bool, } -impl<'a, 'b: 'a> PadAdapter<'a, 'b> { - fn new(fmt: &'a mut fmt::Formatter<'b>) -> PadAdapter<'a, 'b> { - PadAdapter { - fmt, - on_newline: false, - } - } - - fn as_formatter(&mut self) -> fmt::Formatter { - fmt::Formatter { - // These only exist in the struct for the `Formatter::run` method, - // which won’t be used. - curarg: self.fmt.curarg.clone(), - args: self.fmt.args, - - // We want to preserve these - flags: self.fmt.flags, - fill: self.fmt.fill, - align: self.fmt.align, - width: self.fmt.width, - precision: self.fmt.precision, - - // And change this - buf: self, - } +impl<'a> PadAdapter<'a> { + fn wrap<'b, 'c: 'a+'b>(fmt: &'c mut fmt::Formatter, slot: &'b mut Option) + -> fmt::Formatter<'b> { + fmt.wrap_buf(move |buf| { + *slot = Some(PadAdapter { + buf, + on_newline: false, + }); + slot.as_mut().unwrap() + }) } } -impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> { +impl<'a> fmt::Write for PadAdapter<'a> { fn write_str(&mut self, mut s: &str) -> fmt::Result { while !s.is_empty() { if self.on_newline { - self.fmt.write_str(" ")?; + self.buf.write_str(" ")?; } let split = match s.find('\n') { @@ -60,7 +45,7 @@ impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> { s.len() } }; - self.fmt.write_str(&s[..split])?; + self.buf.write_str(&s[..split])?; s = &s[split..]; } @@ -131,13 +116,13 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { }; if self.is_pretty() { - use fmt::Write; - let mut writer = PadAdapter::new(self.fmt); + let mut slot = None; + let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot); writer.write_str(prefix)?; writer.write_str("\n")?; writer.write_str(name)?; writer.write_str(": ")?; - value.fmt(&mut writer.as_formatter()) + value.fmt(&mut writer) } else { write!(self.fmt, "{} {}: ", prefix, name)?; value.fmt(self.fmt) @@ -228,11 +213,11 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { }; if self.is_pretty() { - use fmt::Write; - let mut writer = PadAdapter::new(self.fmt); + let mut slot = None; + let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot); writer.write_str(prefix)?; writer.write_str("\n")?; - value.fmt(&mut writer.as_formatter()) + value.fmt(&mut writer) } else { self.fmt.write_str(prefix)?; self.fmt.write_str(space)?; @@ -276,14 +261,14 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { fn entry(&mut self, entry: &fmt::Debug) { self.result = self.result.and_then(|_| { if self.is_pretty() { - use fmt::Write; - let mut writer = PadAdapter::new(self.fmt); + let mut slot = None; + let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot); writer.write_str(if self.has_fields { ",\n" } else { "\n" })?; - entry.fmt(&mut writer.as_formatter()) + entry.fmt(&mut writer) } else { if self.has_fields { self.fmt.write_str(", ")? @@ -500,16 +485,16 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { pub fn entry(&mut self, key: &fmt::Debug, value: &fmt::Debug) -> &mut DebugMap<'a, 'b> { self.result = self.result.and_then(|_| { if self.is_pretty() { - use fmt::Write; - let mut writer = PadAdapter::new(self.fmt); + let mut slot = None; + let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot); writer.write_str(if self.has_fields { ",\n" } else { "\n" })?; - key.fmt(&mut writer.as_formatter())?; + key.fmt(&mut writer)?; writer.write_str(": ")?; - value.fmt(&mut writer.as_formatter()) + value.fmt(&mut writer) } else { if self.has_fields { self.fmt.write_str(", ")? diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 897222747f5..34f2c4ce09d 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1014,6 +1014,27 @@ pub fn write(output: &mut Write, args: Arguments) -> Result { } impl<'a> Formatter<'a> { + fn wrap_buf<'b, 'c, F>(&'b mut self, wrap: F) -> Formatter<'c> + where 'b: 'c, F: FnOnce(&'b mut (Write+'b)) -> &'c mut (Write+'c) + { + Formatter { + // We want to change this + buf: wrap(self.buf), + + // And preserve these + flags: self.flags, + fill: self.fill, + align: self.align, + width: self.width, + precision: self.precision, + + // These only exist in the struct for the `run` method, + // which won’t be used together with this method. + curarg: self.curarg.clone(), + args: self.args, + } + } + // First up is the collection of functions used to execute a format string // at runtime. This consumes all of the compile-time statics generated by // the format! syntax extension. -- cgit 1.4.1-3-g733a5