1414
1515use any;
1616use cell:: { Cell , Ref , RefMut } ;
17+ use cmp;
1718use collections:: Collection ;
19+ use f32;
1820use iter:: { Iterator , range} ;
1921use kinds:: Copy ;
2022use mem;
23+ use num:: FPNormal ;
2124use option:: { Option , Some , None } ;
2225use ops:: Deref ;
2326use result:: { Ok , Err } ;
@@ -171,6 +174,11 @@ impl<'a> Show for Arguments<'a> {
171174pub trait Show {
172175 /// Formats the value using the given formatter.
173176 fn fmt ( & self , & mut Formatter ) -> Result ;
177+
178+ /// Returns a conservative estimate of the size of the formatted string.
179+ ///
180+ /// A return of `None` means a close estimate is costly or not feasible.
181+ fn formatter_len_hint ( & self ) -> Option < uint > { None }
174182}
175183
176184/// Format trait for the `b` character
@@ -260,7 +268,7 @@ macro_rules! uniform_fn_call_workaround {
260268 pub fn $name<T : $trait_>( x: & T , fmt: & mut Formatter ) -> Result {
261269 x. fmt( fmt)
262270 }
263- ) *
271+ ) *
264272 }
265273}
266274uniform_fn_call_workaround ! {
@@ -591,6 +599,7 @@ impl<'a, T: Show> Show for &'a mut T {
591599}
592600impl < ' a > Show for & ' a Show +' a {
593601 fn fmt ( & self , f : & mut Formatter ) -> Result { ( * self ) . fmt ( f) }
602+ fn formatter_len_hint ( & self ) -> Option < uint > { #![ inline] ( * self ) . formatter_len_hint ( ) }
594603}
595604
596605impl Bool for bool {
@@ -705,20 +714,69 @@ macro_rules! floating(($ty:ident) => {
705714floating ! ( f32 )
706715floating ! ( f64 )
707716
717+ fn formatter_len_hint_string ( this : & & str ) -> Option < uint > {
718+ Some ( this. len ( ) )
719+ }
720+
721+ fn formatter_len_hint_bool ( _: & bool ) -> Option < uint > {
722+ Some ( 5 )
723+ }
724+
725+ fn formatter_len_hint_char ( _: & char ) -> Option < uint > {
726+ Some ( 4 )
727+ }
728+
729+ static LOG10_2 : f32 = f32:: consts:: LOG10_E / f32:: consts:: LOG2_E ;
730+ static SHIFTED_LOG10_2 : i32 = ( LOG10_2 * ( 1 u << 16 ) as f32 ) as i32 ;
731+
732+ fn formatter_len_hint_float_f32 ( this : & f32 ) -> Option < uint > {
733+ use num:: { Float , Signed } ;
734+
735+ match this. classify ( ) {
736+ FPNormal => {
737+ let ( _, exponent, _) = this. integer_decode ( ) ;
738+ // A fast approximate log_10. Add a small value at the end for the
739+ // sign and decimal separator.
740+ let log_10 = ( ( exponent as i32 + 23 ) * SHIFTED_LOG10_2 ) >> 16 ;
741+ Some ( cmp:: max ( log_10, -5 ) . abs ( ) as uint + 4 )
742+ }
743+ // Otherwise, "+inf" is the longest string we might print.
744+ _ => Some ( 4 )
745+ }
746+ }
747+
748+ fn formatter_len_hint_float_f64 ( this : & f64 ) -> Option < uint > {
749+ use num:: { Float , Signed } ;
750+
751+ match this. classify ( ) {
752+ FPNormal => {
753+ let ( _, exponent, _) = this. integer_decode ( ) ;
754+ let log_10 = ( ( exponent as i32 + 52 ) * SHIFTED_LOG10_2 ) >> 16 ;
755+ Some ( cmp:: max ( log_10, -5 ) . abs ( ) as uint + 4 )
756+ }
757+ // Otherwise, "+inf" is the longest string we might print.
758+ _ => Some ( 4 )
759+ }
760+ }
761+
708762// Implementation of Show for various core types
709763
710- macro_rules! delegate( ( $ty: ty to $other: ident) => {
764+ macro_rules! delegate( ( $ty: ty to $other: ident $ ( $suffix : ident ) * ) => {
711765 impl <' a> Show for $ty {
712766 fn fmt( & self , f: & mut Formatter ) -> Result {
713767 ( concat_idents!( secret_, $other) ( self , f) )
714768 }
769+ #[ inline]
770+ fn formatter_len_hint( & self ) -> Option <uint> {
771+ ( concat_idents!( formatter_len_hint_, $other, $( $suffix) ,* ) ( self ) )
772+ }
715773 }
716774} )
717775delegate ! ( & ' a str to string)
718776delegate ! ( bool to bool )
719777delegate ! ( char to char )
720- delegate ! ( f32 to float)
721- delegate ! ( f64 to float)
778+ delegate ! ( f32 to float _f32 )
779+ delegate ! ( f64 to float _f64 )
722780
723781impl < T > Show for * const T {
724782 fn fmt ( & self , f : & mut Formatter ) -> Result { secret_pointer ( self , f) }
@@ -792,6 +850,11 @@ impl Show for () {
792850 fn fmt ( & self , f : & mut Formatter ) -> Result {
793851 f. pad ( "()" )
794852 }
853+
854+ #[ inline]
855+ fn formatter_len_hint ( & self ) -> Option < uint > {
856+ Some ( 2 )
857+ }
795858}
796859
797860impl < T : Copy + Show > Show for Cell < T > {
@@ -804,12 +867,22 @@ impl<'b, T: Show> Show for Ref<'b, T> {
804867 fn fmt ( & self , f : & mut Formatter ) -> Result {
805868 ( * * self ) . fmt ( f)
806869 }
870+
871+ #[ inline]
872+ fn formatter_len_hint ( & self ) -> Option < uint > {
873+ ( * * self ) . formatter_len_hint ( )
874+ }
807875}
808876
809877impl < ' b , T : Show > Show for RefMut < ' b , T > {
810878 fn fmt ( & self , f : & mut Formatter ) -> Result {
811879 ( * ( self . deref ( ) ) ) . fmt ( f)
812880 }
881+
882+ #[ inline]
883+ fn formatter_len_hint ( & self ) -> Option < uint > {
884+ ( * ( self . deref ( ) ) ) . formatter_len_hint ( )
885+ }
813886}
814887
815888// If you expected tests to be here, look instead at the run-pass/ifmt.rs test,
0 commit comments