@@ -630,45 +630,39 @@ impl<'a> Arguments<'a> {
630630 /// when using `format!`. Note: this is neither the lower nor upper bound.
631631 #[ inline]
632632 pub fn estimated_capacity ( & self ) -> usize {
633+ if let Some ( s) = self . as_str ( ) {
634+ return s. len ( ) ;
635+ }
633636 // Iterate over the template, counting the length of literal pieces.
634637 let mut length = 0usize ;
635638 let mut starts_with_placeholder = false ;
636639 let mut template = self . template ;
637- let mut has_placeholders = false ;
638640 loop {
639641 // SAFETY: We can assume the template is valid.
640642 unsafe {
641- let n = template. next ( ) . i ;
643+ let n = template. next_piece ( ) . i ;
642644 if n == 0 {
643645 // End of template.
644646 break ;
645647 } else if n <= isize:: MAX as _ {
646648 // Literal string piece.
647- if length != 0 {
648- // More than one literal string piece means we have placeholders.
649- has_placeholders = true ;
650- }
651649 length += n as usize ;
652- let _ptr = template. next ( ) ; // Skip the string pointer.
650+ let _ptr = template. next_piece ( ) ; // Skip the string pointer.
653651 } else {
654652 // Placeholder piece.
655653 if length == 0 {
656654 starts_with_placeholder = true ;
657655 }
658- has_placeholders = true ;
659656 // Skip remainder of placeholder:
660657 #[ cfg( target_pointer_width = "32" ) ]
661- let _ = template. next ( ) ;
658+ let _ = template. next_piece ( ) ;
662659 #[ cfg( target_pointer_width = "16" ) ]
663- let _ = ( template. next ( ) , template. next ( ) , template. next ( ) ) ;
660+ let _ = ( template. next_piece ( ) , template. next_piece ( ) , template. next_piece ( ) ) ;
664661 }
665662 }
666663 }
667664
668- if !has_placeholders {
669- // If the template has no placeholders, we know the length exactly.
670- length
671- } else if starts_with_placeholder && length < 16 {
665+ if starts_with_placeholder && length < 16 {
672666 // If the format string starts with a placeholder,
673667 // don't preallocate anything, unless length
674668 // of literal pieces is significant.
@@ -730,27 +724,17 @@ impl<'a> Arguments<'a> {
730724 #[ must_use]
731725 #[ inline]
732726 pub const fn as_str ( & self ) -> Option < & ' static str > {
733- let mut template = self . template ;
734- // SAFETY: We can assume the template is valid.
735- let n = unsafe { template. next ( ) . i } ;
736- if n == 0 {
737- // The template is empty.
738- return Some ( "" ) ;
739- }
740- if n <= isize:: MAX as _ {
741- // Template starts with a string piece.
742- // SAFETY: We can assume the template is valid.
743- unsafe {
744- let ptr = template. next ( ) . p ;
745- if template. next ( ) . i == 0 {
746- // The template has only one piece.
747- return Some ( str:: from_utf8_unchecked ( crate :: slice:: from_raw_parts (
748- ptr, n as usize ,
749- ) ) ) ;
750- }
751- }
727+ if let Some ( len) = self . template . as_str_len ( ) {
728+ // SAFETY: This fmt::Arguments stores a &'static str.
729+ Some ( unsafe {
730+ str:: from_utf8_unchecked ( crate :: slice:: from_raw_parts (
731+ self . args . cast ( ) . as_ptr ( ) ,
732+ len,
733+ ) )
734+ } )
735+ } else {
736+ None
752737 }
753- None
754738 }
755739
756740 /// Same as [`Arguments::as_str`], but will only return `Some(s)` if it can be determined at compile time.
@@ -1493,6 +1477,10 @@ pub trait UpperExp: PointeeSized {
14931477/// [`write!`]: crate::write!
14941478#[ stable( feature = "rust1" , since = "1.0.0" ) ]
14951479pub fn write ( output : & mut dyn Write , fmt : Arguments < ' _ > ) -> Result {
1480+ if let Some ( s) = fmt. as_str ( ) {
1481+ return output. write_str ( s) ;
1482+ }
1483+
14961484 let mut template = fmt. template ;
14971485 let args = fmt. args ;
14981486
@@ -1501,7 +1489,7 @@ pub fn write(output: &mut dyn Write, fmt: Arguments<'_>) -> Result {
15011489
15021490 loop {
15031491 // SAFETY: We can assume the template is valid.
1504- let n = unsafe { template. next ( ) . i } ;
1492+ let n = unsafe { template. next_piece ( ) . i } ;
15051493 if n == 0 {
15061494 // End of template.
15071495 return Ok ( ( ) ) ;
@@ -1518,7 +1506,7 @@ pub fn write(output: &mut dyn Write, fmt: Arguments<'_>) -> Result {
15181506 unsafe { arg. fmt ( & mut Formatter :: new ( output, options) ) } ?;
15191507 }
15201508 // SAFETY: We can assume the strings in the template are valid.
1521- let s = unsafe { crate :: str:: from_raw_parts ( template. next ( ) . p , n as usize ) } ;
1509+ let s = unsafe { crate :: str:: from_raw_parts ( template. next_piece ( ) . p , n as usize ) } ;
15221510 output. write_str ( s) ?;
15231511 last_piece_was_str = true ;
15241512 } else {
@@ -1527,13 +1515,13 @@ pub fn write(output: &mut dyn Write, fmt: Arguments<'_>) -> Result {
15271515 let ( high, low) = ( ( n >> 32 ) as u32 , n as u32 ) ;
15281516 #[ cfg( target_pointer_width = "32" ) ]
15291517 // SAFETY: We can assume the template is valid.
1530- let ( high, low) = ( n as u32 , unsafe { template. next ( ) . i } as u32 ) ;
1518+ let ( high, low) = ( n as u32 , unsafe { template. next_piece ( ) . i } as u32 ) ;
15311519 #[ cfg( target_pointer_width = "16" ) ]
15321520 // SAFETY: We can assume the template is valid.
15331521 let ( high, low) = unsafe {
15341522 (
1535- ( n as u32 ) << 16 | template. next ( ) . i as u32 ,
1536- ( template. next ( ) . i as u32 ) << 16 | template. next ( ) . i as u32 ,
1523+ ( n as u32 ) << 16 | template. next_piece ( ) . i as u32 ,
1524+ ( template. next_piece ( ) . i as u32 ) << 16 | template. next_piece ( ) . i as u32 ,
15371525 )
15381526 } ;
15391527 let arg_index = ( low & 0x3FF ) as usize ;
0 commit comments