14
14
15
15
use any;
16
16
use cell:: { Cell , Ref , RefMut } ;
17
+ use cmp;
17
18
use collections:: Collection ;
19
+ use f32;
18
20
use iter:: { Iterator , range} ;
19
21
use kinds:: Copy ;
20
22
use mem;
23
+ use num:: FPNormal ;
21
24
use option:: { Option , Some , None } ;
22
25
use ops:: Deref ;
23
26
use result:: { Ok , Err } ;
@@ -171,6 +174,11 @@ impl<'a> Show for Arguments<'a> {
171
174
pub trait Show {
172
175
/// Formats the value using the given formatter.
173
176
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 }
174
182
}
175
183
176
184
/// Format trait for the `b` character
@@ -260,7 +268,7 @@ macro_rules! uniform_fn_call_workaround {
260
268
pub fn $name<T : $trait_>( x: & T , fmt: & mut Formatter ) -> Result {
261
269
x. fmt( fmt)
262
270
}
263
- ) *
271
+ ) *
264
272
}
265
273
}
266
274
uniform_fn_call_workaround ! {
@@ -591,6 +599,7 @@ impl<'a, T: Show> Show for &'a mut T {
591
599
}
592
600
impl < ' a > Show for & ' a Show +' a {
593
601
fn fmt ( & self , f : & mut Formatter ) -> Result { ( * self ) . fmt ( f) }
602
+ fn formatter_len_hint ( & self ) -> Option < uint > { #![ inline] ( * self ) . formatter_len_hint ( ) }
594
603
}
595
604
596
605
impl Bool for bool {
@@ -705,20 +714,69 @@ macro_rules! floating(($ty:ident) => {
705
714
floating ! ( f32 )
706
715
floating ! ( f64 )
707
716
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
+
708
762
// Implementation of Show for various core types
709
763
710
- macro_rules! delegate( ( $ty: ty to $other: ident) => {
764
+ macro_rules! delegate( ( $ty: ty to $other: ident $ ( $suffix : ident ) * ) => {
711
765
impl <' a> Show for $ty {
712
766
fn fmt( & self , f: & mut Formatter ) -> Result {
713
767
( concat_idents!( secret_, $other) ( self , f) )
714
768
}
769
+ #[ inline]
770
+ fn formatter_len_hint( & self ) -> Option <uint> {
771
+ ( concat_idents!( formatter_len_hint_, $other, $( $suffix) ,* ) ( self ) )
772
+ }
715
773
}
716
774
} )
717
775
delegate ! ( & ' a str to string)
718
776
delegate ! ( bool to bool )
719
777
delegate ! ( 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 )
722
780
723
781
impl < T > Show for * const T {
724
782
fn fmt ( & self , f : & mut Formatter ) -> Result { secret_pointer ( self , f) }
@@ -792,6 +850,11 @@ impl Show for () {
792
850
fn fmt ( & self , f : & mut Formatter ) -> Result {
793
851
f. pad ( "()" )
794
852
}
853
+
854
+ #[ inline]
855
+ fn formatter_len_hint ( & self ) -> Option < uint > {
856
+ Some ( 2 )
857
+ }
795
858
}
796
859
797
860
impl < T : Copy + Show > Show for Cell < T > {
@@ -804,12 +867,22 @@ impl<'b, T: Show> Show for Ref<'b, T> {
804
867
fn fmt ( & self , f : & mut Formatter ) -> Result {
805
868
( * * self ) . fmt ( f)
806
869
}
870
+
871
+ #[ inline]
872
+ fn formatter_len_hint ( & self ) -> Option < uint > {
873
+ ( * * self ) . formatter_len_hint ( )
874
+ }
807
875
}
808
876
809
877
impl < ' b , T : Show > Show for RefMut < ' b , T > {
810
878
fn fmt ( & self , f : & mut Formatter ) -> Result {
811
879
( * ( self . deref ( ) ) ) . fmt ( f)
812
880
}
881
+
882
+ #[ inline]
883
+ fn formatter_len_hint ( & self ) -> Option < uint > {
884
+ ( * ( self . deref ( ) ) ) . formatter_len_hint ( )
885
+ }
813
886
}
814
887
815
888
// If you expected tests to be here, look instead at the run-pass/ifmt.rs test,
0 commit comments