@@ -1036,6 +1036,27 @@ pub fn write(output: &mut dyn Write, args: Arguments) -> Result {
10361036 Ok ( ( ) )
10371037}
10381038
1039+ /// Padding after the end of something. Returned by `Formatter::padding`.
1040+ #[ must_use = "don't forget to write the post padding" ]
1041+ struct PostPadding {
1042+ fill : char ,
1043+ padding : usize ,
1044+ }
1045+
1046+ impl PostPadding {
1047+ fn new ( fill : char , padding : usize ) -> PostPadding {
1048+ PostPadding { fill, padding }
1049+ }
1050+
1051+ /// Write this post padding.
1052+ fn write ( self , buf : & mut dyn Write ) -> Result {
1053+ for _ in 0 ..self . padding {
1054+ buf. write_char ( self . fill ) ?;
1055+ }
1056+ Ok ( ( ) )
1057+ }
1058+ }
1059+
10391060impl < ' a > Formatter < ' a > {
10401061 fn wrap_buf < ' b , ' c , F > ( & ' b mut self , wrap : F ) -> Formatter < ' c >
10411062 where ' b : ' c , F : FnOnce ( & ' b mut ( dyn Write +' b ) ) -> & ' c mut ( dyn Write +' c )
@@ -1153,47 +1174,56 @@ impl<'a> Formatter<'a> {
11531174 sign = Some ( '+' ) ; width += 1 ;
11541175 }
11551176
1156- let prefixed = self . alternate ( ) ;
1157- if prefixed {
1177+ let prefix = if self . alternate ( ) {
11581178 width += prefix. chars ( ) . count ( ) ;
1159- }
1179+ Some ( prefix)
1180+ } else {
1181+ None
1182+ } ;
11601183
11611184 // Writes the sign if it exists, and then the prefix if it was requested
1162- let write_prefix = |f : & mut Formatter | {
1185+ #[ inline( never) ]
1186+ fn write_prefix ( f : & mut Formatter , sign : Option < char > , prefix : Option < & str > ) -> Result {
11631187 if let Some ( c) = sign {
11641188 f. buf . write_char ( c) ?;
11651189 }
1166- if prefixed { f. buf . write_str ( prefix) }
1167- else { Ok ( ( ) ) }
1168- } ;
1190+ if let Some ( prefix) = prefix {
1191+ f. buf . write_str ( prefix)
1192+ } else {
1193+ Ok ( ( ) )
1194+ }
1195+ }
11691196
11701197 // The `width` field is more of a `min-width` parameter at this point.
11711198 match self . width {
11721199 // If there's no minimum length requirements then we can just
11731200 // write the bytes.
11741201 None => {
1175- write_prefix ( self ) ?; self . buf . write_str ( buf)
1202+ write_prefix ( self , sign, prefix) ?;
1203+ self . buf . write_str ( buf)
11761204 }
11771205 // Check if we're over the minimum width, if so then we can also
11781206 // just write the bytes.
11791207 Some ( min) if width >= min => {
1180- write_prefix ( self ) ?; self . buf . write_str ( buf)
1208+ write_prefix ( self , sign, prefix) ?;
1209+ self . buf . write_str ( buf)
11811210 }
11821211 // The sign and prefix goes before the padding if the fill character
11831212 // is zero
11841213 Some ( min) if self . sign_aware_zero_pad ( ) => {
11851214 self . fill = '0' ;
11861215 self . align = rt:: v1:: Alignment :: Right ;
1187- write_prefix ( self ) ?;
1188- self . with_padding ( min - width, rt:: v1:: Alignment :: Right , |f| {
1189- f . buf . write_str ( buf)
1190- } )
1216+ write_prefix ( self , sign , prefix ) ?;
1217+ let post_padding = self . padding ( min - width, rt:: v1:: Alignment :: Right ) ? ;
1218+ self . buf . write_str ( buf) ? ;
1219+ post_padding . write ( self . buf )
11911220 }
11921221 // Otherwise, the sign and prefix goes after the padding
11931222 Some ( min) => {
1194- self . with_padding ( min - width, rt:: v1:: Alignment :: Right , |f| {
1195- write_prefix ( f) ?; f. buf . write_str ( buf)
1196- } )
1223+ let post_padding = self . padding ( min - width, rt:: v1:: Alignment :: Right ) ?;
1224+ write_prefix ( self , sign, prefix) ?;
1225+ self . buf . write_str ( buf) ?;
1226+ post_padding. write ( self . buf )
11971227 }
11981228 }
11991229 }
@@ -1264,19 +1294,21 @@ impl<'a> Formatter<'a> {
12641294 // up the minimum width with the specified string + some alignment.
12651295 Some ( width) => {
12661296 let align = rt:: v1:: Alignment :: Left ;
1267- self . with_padding ( width - s. chars ( ) . count ( ) , align, |me| {
1268- me . buf . write_str ( s)
1269- } )
1297+ let post_padding = self . padding ( width - s. chars ( ) . count ( ) , align) ? ;
1298+ self . buf . write_str ( s) ? ;
1299+ post_padding . write ( self . buf )
12701300 }
12711301 }
12721302 }
12731303
1274- /// Runs a callback, emitting the correct padding either before or
1275- /// afterwards depending on whether right or left alignment is requested.
1276- fn with_padding < F > ( & mut self , padding : usize , default : rt:: v1:: Alignment ,
1277- f : F ) -> Result
1278- where F : FnOnce ( & mut Formatter ) -> Result ,
1279- {
1304+ /// Write the pre-padding and return the unwritten post-padding. Callers are
1305+ /// responsible for ensuring post-padding is written after the thing that is
1306+ /// being padded.
1307+ fn padding (
1308+ & mut self ,
1309+ padding : usize ,
1310+ default : rt:: v1:: Alignment
1311+ ) -> result:: Result < PostPadding , Error > {
12801312 let align = match self . align {
12811313 rt:: v1:: Alignment :: Unknown => default,
12821314 _ => self . align
@@ -1289,20 +1321,11 @@ impl<'a> Formatter<'a> {
12891321 rt:: v1:: Alignment :: Center => ( padding / 2 , ( padding + 1 ) / 2 ) ,
12901322 } ;
12911323
1292- let mut fill = [ 0 ; 4 ] ;
1293- let fill = self . fill . encode_utf8 ( & mut fill) ;
1294-
12951324 for _ in 0 ..pre_pad {
1296- self . buf . write_str ( fill) ?;
1297- }
1298-
1299- f ( self ) ?;
1300-
1301- for _ in 0 ..post_pad {
1302- self . buf . write_str ( fill) ?;
1325+ self . buf . write_char ( self . fill ) ?;
13031326 }
13041327
1305- Ok ( ( ) )
1328+ Ok ( PostPadding :: new ( self . fill , post_pad ) )
13061329 }
13071330
13081331 /// Takes the formatted parts and applies the padding.
@@ -1334,9 +1357,9 @@ impl<'a> Formatter<'a> {
13341357 let ret = if width <= len { // no padding
13351358 self . write_formatted_parts ( & formatted)
13361359 } else {
1337- self . with_padding ( width - len, align, |f| {
1338- f . write_formatted_parts ( & formatted)
1339- } )
1360+ let post_padding = self . padding ( width - len, align) ? ;
1361+ self . write_formatted_parts ( & formatted) ? ;
1362+ post_padding . write ( self . buf )
13401363 } ;
13411364 self . fill = old_fill;
13421365 self . align = old_align;
0 commit comments