@@ -1693,49 +1693,41 @@ impl<'a> Formatter<'a> {
16931693 /// ```
16941694 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
16951695 pub fn pad ( & mut self , s : & str ) -> Result {
1696- // Make sure there's a fast path up front
1696+ // Make sure there's a fast path up front.
16971697 if self . options . width . is_none ( ) && self . options . precision . is_none ( ) {
16981698 return self . buf . write_str ( s) ;
16991699 }
1700- // The `precision` field can be interpreted as a `max-width` for the
1700+
1701+ // The `precision` field can be interpreted as a maximum width for the
17011702 // string being formatted.
1702- let s = if let Some ( max) = self . options . precision {
1703- // If our string is longer that the precision, then we must have
1704- // truncation. However other flags like `fill`, `width` and `align`
1705- // must act as always.
1706- if let Some ( ( i, _) ) = s. char_indices ( ) . nth ( max) {
1707- // LLVM here can't prove that `..i` won't panic `&s[..i]`, but
1708- // we know that it can't panic. Use `get` + `unwrap_or` to avoid
1709- // `unsafe` and otherwise don't emit any panic-related code
1710- // here.
1711- s. get ( ..i) . unwrap_or ( s)
1712- } else {
1713- & s
1714- }
1703+ let ( s, char_count) = if let Some ( max_char_count) = self . options . precision {
1704+ let mut iter = s. char_indices ( ) ;
1705+ let remaining = match iter. advance_by ( max_char_count) {
1706+ Ok ( ( ) ) => 0 ,
1707+ Err ( remaining) => remaining. get ( ) ,
1708+ } ;
1709+ // SAFETY: The offset of `.char_indices()` is guaranteed to be
1710+ // in-bounds and between character boundaries.
1711+ let truncated = unsafe { s. get_unchecked ( ..iter. offset ( ) ) } ;
1712+ ( truncated, max_char_count - remaining)
17151713 } else {
1716- & s
1714+ // Use the optimized char counting algorithm for the full string.
1715+ ( s, s. chars ( ) . count ( ) )
17171716 } ;
1718- // The `width` field is more of a `min-width` parameter at this point.
1719- match self . options . width {
1720- // If we're under the maximum length, and there's no minimum length
1721- // requirements, then we can just emit the string
1722- None => self . buf . write_str ( s) ,
1723- Some ( width) => {
1724- let chars_count = s. chars ( ) . count ( ) ;
1725- // If we're under the maximum width, check if we're over the minimum
1726- // width, if so it's as easy as just emitting the string.
1727- if chars_count >= width {
1728- self . buf . write_str ( s)
1729- }
1730- // If we're under both the maximum and the minimum width, then fill
1731- // up the minimum width with the specified string + some alignment.
1732- else {
1733- let align = Alignment :: Left ;
1734- let post_padding = self . padding ( width - chars_count, align) ?;
1735- self . buf . write_str ( s) ?;
1736- post_padding. write ( self )
1737- }
1738- }
1717+
1718+ // The `width` field is more of a minimum width parameter at this point.
1719+ if let Some ( width) = self . options . width
1720+ && char_count < width
1721+ {
1722+ // If we're under the minimum width, then fill up the minimum width
1723+ // with the specified string + some alignment.
1724+ let post_padding = self . padding ( width - char_count, Alignment :: Left ) ?;
1725+ self . buf . write_str ( s) ?;
1726+ post_padding. write ( self )
1727+ } else {
1728+ // If we're over the minimum width or there is no minimum width, we
1729+ // can just emit the string.
1730+ self . buf . write_str ( s)
17391731 }
17401732 }
17411733
0 commit comments