@@ -1693,49 +1693,37 @@ 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 max_chars_count = self . options . precision . unwrap_or ( usize:: MAX ) ;
1704+ let mut iter = s. chars ( ) ;
1705+ let chars_count = iter. by_ref ( ) . take ( max_chars_count) . count ( ) ;
1706+
1707+ // If our string is longer than the maximum width, truncate it and
1708+ // handle other flags in terms of the truncated string.
1709+ let byte_len = s. len ( ) - iter. as_str ( ) . len ( ) ;
1710+ // SAFETY: The index is derived from the offset of `.chars()`, which is
1711+ // guaranteed to be in-bounds and between character boundaries.
1712+ let s = unsafe { s. get_unchecked ( ..byte_len) } ;
1713+
1714+ // The `width` field is more of a minimum width parameter at this point.
1715+ if let Some ( width) = self . options . width
1716+ && chars_count < width
1717+ {
1718+ // If we're under the minimum width, then fill up the minimum width
1719+ // with the specified string + some alignment.
1720+ let post_padding = self . padding ( width - chars_count, Alignment :: Left ) ?;
1721+ self . buf . write_str ( s) ?;
1722+ post_padding. write ( self )
17151723 } else {
1716- & s
1717- } ;
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- }
1724+ // If we're over the minimum width or there is no minimum width, we
1725+ // can just emit the string.
1726+ self . buf . write_str ( s)
17391727 }
17401728 }
17411729
0 commit comments