@@ -1777,19 +1777,12 @@ impl<'a> Formatter<'a> {
17771777 // Helper methods used for padding and processing formatting arguments that
17781778 // all formatting traits can use.
17791779
1780- /// Performs the correct padding for an integer which has already been
1781- /// emitted into a str. The str should *not* contain the sign for the
1782- /// integer, that will be added by this method.
1783- ///
1784- /// # Arguments
1785- ///
1786- /// * is_nonnegative - whether the original integer was either positive or zero.
1787- /// * prefix - if the '#' character (Alternate) is provided, this
1788- /// is the prefix to put in front of the number.
1789- /// * buf - the byte array that the number has been formatted into
1790- ///
1791- /// This function will correctly account for the flags provided as well as
1792- /// the minimum width. It will not take precision into account.
1780+ /// Write a formatted integer to the Formatter. The `digits` string should
1781+ /// hold the representation of the absolute value, without sign. Whether a
1782+ /// sign ("+" or "-") is written depends both on format paramaters and on
1783+ /// `is_nonnegative`. The `prefix` (e.g., "0x") is written when alternate.
1784+ /// Padding may be included when width is Some. The precision is ignored
1785+ /// for integers.
17931786 ///
17941787 /// # Examples
17951788 ///
@@ -1822,8 +1815,8 @@ impl<'a> Formatter<'a> {
18221815 /// assert_eq!(format!("{:0>#8}", Foo::new(-1)), "00-Foo 1");
18231816 /// ```
18241817 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1825- pub fn pad_integral ( & mut self , is_nonnegative : bool , prefix : & str , buf : & str ) -> Result {
1826- let mut width = buf . len ( ) ;
1818+ pub fn pad_integral ( & mut self , is_nonnegative : bool , prefix : & str , digits : & str ) -> Result {
1819+ let mut width = digits . len ( ) ;
18271820
18281821 let mut sign = None ;
18291822 if !is_nonnegative {
@@ -1855,27 +1848,70 @@ impl<'a> Formatter<'a> {
18551848 if width >= usize:: from ( min) {
18561849 // We're over the minimum width, so then we can just write the bytes.
18571850 write_prefix ( self , sign, prefix) ?;
1858- self . buf . write_str ( buf )
1851+ self . buf . write_str ( digits )
18591852 } else if self . sign_aware_zero_pad ( ) {
18601853 // The sign and prefix goes before the padding if the fill character
18611854 // is zero
18621855 let old_options = self . options ;
18631856 self . options . fill ( '0' ) . align ( Some ( Alignment :: Right ) ) ;
18641857 write_prefix ( self , sign, prefix) ?;
18651858 let post_padding = self . padding ( min - width as u16 , Alignment :: Right ) ?;
1866- self . buf . write_str ( buf ) ?;
1859+ self . buf . write_str ( digits ) ?;
18671860 post_padding. write ( self ) ?;
18681861 self . options = old_options;
18691862 Ok ( ( ) )
18701863 } else {
18711864 // Otherwise, the sign and prefix goes after the padding
18721865 let post_padding = self . padding ( min - width as u16 , Alignment :: Right ) ?;
18731866 write_prefix ( self , sign, prefix) ?;
1874- self . buf . write_str ( buf ) ?;
1867+ self . buf . write_str ( digits ) ?;
18751868 post_padding. write ( self )
18761869 }
18771870 }
18781871
1872+ /// Write a formatted number to the Formatter with a closure. The Fn should
1873+ /// write the representation of the absolute value, excluding `sign` (e.g.,
1874+ /// "+" or "-"). The implementation should follow [precision] when present.
1875+ /// The output of `write_abs` must match exactly the `write_len` amount of
1876+ /// `char`s in size. Padding may be written when [width] applies.
1877+ fn pad_number < F > ( & mut self , sign : & str , write_len : usize , write_abs : F ) -> Result
1878+ where
1879+ F : Fn ( & mut Self ) -> Result ,
1880+ {
1881+ let out_len = write_len + sign. len ( ) ;
1882+ // Pad when the width is higher than the output length.
1883+ let pad = self . width ( ) . unwrap_or ( 0 ) . saturating_sub ( out_len) ;
1884+
1885+ if pad == 0 || self . sign_aware_zero_pad ( ) {
1886+ self . write_str ( sign) ?;
1887+ self . write_zeroes ( pad) ?;
1888+ return write_abs ( self ) ;
1889+ }
1890+
1891+ // Numbers align to the right by default.
1892+ let align = self . align ( ) . unwrap_or ( Alignment :: Right ) ;
1893+ let ( pad_before, pad_after) = match align {
1894+ Alignment :: Left => ( 0 , pad) ,
1895+ Alignment :: Right => ( pad, 0 ) ,
1896+ Alignment :: Center => {
1897+ let split = pad / 2 ; // may round down
1898+ ( split, pad - split)
1899+ }
1900+ } ;
1901+
1902+ // Write output with padding.
1903+ let fill = self . fill ( ) ;
1904+ for _ in 0 ..pad_before {
1905+ self . write_char ( fill) ?;
1906+ }
1907+ self . write_str ( sign) ?;
1908+ write_abs ( self ) ?;
1909+ for _ in 0 ..pad_after {
1910+ self . write_char ( fill) ?;
1911+ }
1912+ Ok ( ( ) )
1913+ }
1914+
18791915 /// Takes a string slice and emits it to the internal buffer after applying
18801916 /// the relevant formatting flags specified.
18811917 ///
@@ -1978,50 +2014,6 @@ impl<'a> Formatter<'a> {
19782014 ///
19792015 /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8.
19802016 unsafe fn pad_formatted_parts ( & mut self , formatted : & numfmt:: Formatted < ' _ > ) -> Result {
1981- if self . options . width == 0 {
1982- // this is the common case and we take a shortcut
1983- // SAFETY: Per the precondition.
1984- unsafe { self . write_formatted_parts ( formatted) }
1985- } else {
1986- // for the sign-aware zero padding, we render the sign first and
1987- // behave as if we had no sign from the beginning.
1988- let mut formatted = formatted. clone ( ) ;
1989- let mut width = self . options . width ;
1990- let old_options = self . options ;
1991- if self . sign_aware_zero_pad ( ) {
1992- // a sign always goes first
1993- let sign = formatted. sign ;
1994- self . buf . write_str ( sign) ?;
1995-
1996- // remove the sign from the formatted parts
1997- formatted. sign = "" ;
1998- width = width. saturating_sub ( sign. len ( ) as u16 ) ;
1999- self . options . fill ( '0' ) . align ( Some ( Alignment :: Right ) ) ;
2000- }
2001-
2002- // remaining parts go through the ordinary padding process.
2003- let len = formatted. len ( ) ;
2004- let ret = if usize:: from ( width) <= len {
2005- // no padding
2006- // SAFETY: Per the precondition.
2007- unsafe { self . write_formatted_parts ( & formatted) }
2008- } else {
2009- let post_padding = self . padding ( width - len as u16 , Alignment :: Right ) ?;
2010- // SAFETY: Per the precondition.
2011- unsafe {
2012- self . write_formatted_parts ( & formatted) ?;
2013- }
2014- post_padding. write ( self )
2015- } ;
2016- self . options = old_options;
2017- ret
2018- }
2019- }
2020-
2021- /// # Safety
2022- ///
2023- /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8.
2024- unsafe fn write_formatted_parts ( & mut self , formatted : & numfmt:: Formatted < ' _ > ) -> Result {
20252017 unsafe fn write_bytes ( buf : & mut dyn Write , s : & [ u8 ] ) -> Result {
20262018 // SAFETY: This is used for `numfmt::Part::Num` and `numfmt::Part::Copy`.
20272019 // It's safe to use for `numfmt::Part::Num` since every char `c` is between
@@ -2030,39 +2022,51 @@ impl<'a> Formatter<'a> {
20302022 buf. write_str ( unsafe { str:: from_utf8_unchecked ( s) } )
20312023 }
20322024
2033- if !formatted. sign . is_empty ( ) {
2034- self . buf . write_str ( formatted. sign ) ?;
2035- }
2036- for part in formatted. parts {
2037- match * part {
2038- numfmt:: Part :: Zero ( mut nzeroes) => {
2039- const ZEROES : & str = // 64 zeroes
2040- "0000000000000000000000000000000000000000000000000000000000000000" ;
2041- while nzeroes > ZEROES . len ( ) {
2042- self . buf . write_str ( ZEROES ) ?;
2043- nzeroes -= ZEROES . len ( ) ;
2025+ let sign = formatted. sign ;
2026+ let out_len = formatted. len ( ) - sign. len ( ) ;
2027+ self . pad_number ( sign, out_len, |f : & mut Self | {
2028+ for part in formatted. parts {
2029+ match * part {
2030+ numfmt:: Part :: Zero ( nzeroes) => {
2031+ f. write_zeroes ( nzeroes) ?;
20442032 }
2045- if nzeroes > 0 {
2046- self . buf . write_str ( & ZEROES [ ..nzeroes] ) ?;
2047- }
2048- }
2049- numfmt:: Part :: Num ( mut v) => {
2050- let mut s = [ 0 ; 5 ] ;
2051- let len = part. len ( ) ;
2052- for c in s[ ..len] . iter_mut ( ) . rev ( ) {
2053- * c = b'0' + ( v % 10 ) as u8 ;
2054- v /= 10 ;
2033+ numfmt:: Part :: Num ( mut v) => {
2034+ let mut s = [ 0 ; 5 ] ;
2035+ let len = part. len ( ) ;
2036+ for c in s[ ..len] . iter_mut ( ) . rev ( ) {
2037+ * c = b'0' + ( v % 10 ) as u8 ;
2038+ v /= 10 ;
2039+ }
2040+ // SAFETY: Per the precondition.
2041+ unsafe {
2042+ write_bytes ( f. buf , & s[ ..len] ) ?;
2043+ }
20552044 }
20562045 // SAFETY: Per the precondition.
2057- unsafe {
2058- write_bytes ( self . buf , & s [ ..len ] ) ?;
2059- }
2046+ numfmt :: Part :: Copy ( buf ) => unsafe {
2047+ write_bytes ( f . buf , buf ) ?;
2048+ } ,
20602049 }
2061- // SAFETY: Per the precondition.
2062- numfmt:: Part :: Copy ( buf) => unsafe {
2063- write_bytes ( self . buf , buf) ?;
2064- } ,
20652050 }
2051+ Ok ( ( ) )
2052+ } )
2053+ }
2054+
2055+ /// Write n ASCII digits (U+0030) to the Formatter.
2056+ pub ( crate ) fn write_zeroes ( & mut self , n : usize ) -> Result {
2057+ #[ cfg( feature = "optimize_for_size" ) ]
2058+ {
2059+ for _ in 0 ..n {
2060+ self . write_char ( '0' ) ?;
2061+ }
2062+ }
2063+ #[ cfg( not( feature = "optimize_for_size" ) ) ]
2064+ {
2065+ const ZEROES : & str = "0000000000000000000000000000000000000000000000000000000000000000" ;
2066+ for _ in 0 ..( n / 64 ) {
2067+ self . write_str ( ZEROES ) ?;
2068+ }
2069+ self . write_str ( & ZEROES [ ..( n % 64 ) ] ) ?;
20662070 }
20672071 Ok ( ( ) )
20682072 }
0 commit comments