@@ -20,18 +20,25 @@ use fmt;
2020use num:: Zero ;
2121use ops:: { Div , Rem , Sub } ;
2222use str;
23+ use slice;
24+ use ptr;
25+ use mem;
2326
2427#[ doc( hidden) ]
2528trait Int : Zero + PartialEq + PartialOrd + Div < Output =Self > + Rem < Output =Self > +
2629 Sub < Output =Self > + Copy {
2730 fn from_u8 ( u : u8 ) -> Self ;
2831 fn to_u8 ( & self ) -> u8 ;
32+ fn to_u32 ( & self ) -> u32 ;
33+ fn to_u64 ( & self ) -> u64 ;
2934}
3035
3136macro_rules! doit {
3237 ( $( $t: ident) * ) => ( $( impl Int for $t {
3338 fn from_u8( u: u8 ) -> $t { u as $t }
3439 fn to_u8( & self ) -> u8 { * self as u8 }
40+ fn to_u32( & self ) -> u32 { * self as u32 }
41+ fn to_u64( & self ) -> u64 { * self as u64 }
3542 } ) * )
3643}
3744doit ! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
@@ -188,6 +195,7 @@ macro_rules! radix_fmt {
188195 }
189196 }
190197}
198+
191199macro_rules! int_base {
192200 ( $Trait: ident for $T: ident as $U: ident -> $Radix: ident) => {
193201 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -209,17 +217,16 @@ macro_rules! debug {
209217 }
210218 }
211219}
220+
212221macro_rules! integer {
213222 ( $Int: ident, $Uint: ident) => {
214- int_base! { Display for $Int as $Int -> Decimal }
215223 int_base! { Binary for $Int as $Uint -> Binary }
216224 int_base! { Octal for $Int as $Uint -> Octal }
217225 int_base! { LowerHex for $Int as $Uint -> LowerHex }
218226 int_base! { UpperHex for $Int as $Uint -> UpperHex }
219227 radix_fmt! { $Int as $Int, fmt_int }
220228 debug! { $Int }
221229
222- int_base! { Display for $Uint as $Uint -> Decimal }
223230 int_base! { Binary for $Uint as $Uint -> Binary }
224231 int_base! { Octal for $Uint as $Uint -> Octal }
225232 int_base! { LowerHex for $Uint as $Uint -> LowerHex }
@@ -233,3 +240,80 @@ integer! { i8, u8 }
233240integer ! { i16 , u16 }
234241integer ! { i32 , u32 }
235242integer ! { i64 , u64 }
243+
244+ const DEC_DIGITS_LUT : & ' static [ u8 ] =
245+ b"0001020304050607080910111213141516171819\
246+ 2021222324252627282930313233343536373839\
247+ 4041424344454647484950515253545556575859\
248+ 6061626364656667686970717273747576777879\
249+ 8081828384858687888990919293949596979899";
250+
251+ macro_rules! impl_Display {
252+ ( $( $t: ident) ,* : $conv_fn: ident) => ( $(
253+ impl fmt:: Display for $t {
254+ #[ allow( unused_comparisons) ]
255+ fn fmt( & self , f: & mut fmt:: Formatter ) -> fmt:: Result {
256+ let is_positive = * self >= 0 ;
257+ let mut n = if is_positive {
258+ self . $conv_fn( )
259+ } else {
260+ // convert the negative num to positive by summing 1 to it's 2 complement
261+ ( !self . $conv_fn( ) ) . wrapping_add( 1 )
262+ } ;
263+ let mut buf: [ u8 ; 20 ] = unsafe { mem:: uninitialized( ) } ;
264+ let mut curr = buf. len( ) as isize ;
265+ let buf_ptr = buf. as_mut_ptr( ) ;
266+ let lut_ptr = DEC_DIGITS_LUT . as_ptr( ) ;
267+
268+ unsafe {
269+ // eagerly decode 4 characters at a time
270+ if <$t>:: max_value( ) as u64 >= 10000 {
271+ while n >= 10000 {
272+ let rem = ( n % 10000 ) as isize ;
273+ n /= 10000 ;
274+
275+ let d1 = ( rem / 100 ) << 1 ;
276+ let d2 = ( rem % 100 ) << 1 ;
277+ curr -= 4 ;
278+ ptr:: copy_nonoverlapping( lut_ptr. offset( d1) , buf_ptr. offset( curr) , 2 ) ;
279+ ptr:: copy_nonoverlapping( lut_ptr. offset( d2) , buf_ptr. offset( curr + 2 ) , 2 ) ;
280+ }
281+ }
282+
283+ // if we reach here numbers are <= 9999, so at most 4 chars long
284+ let mut n = n as isize ; // possibly reduce 64bit math
285+
286+ // decode 2 more chars, if > 2 chars
287+ if n >= 100 {
288+ let d1 = ( n % 100 ) << 1 ;
289+ n /= 100 ;
290+ curr -= 2 ;
291+ ptr:: copy_nonoverlapping( lut_ptr. offset( d1) , buf_ptr. offset( curr) , 2 ) ;
292+ }
293+
294+ // decode last 1 or 2 chars
295+ if n < 10 {
296+ curr -= 1 ;
297+ * buf_ptr. offset( curr) = ( n as u8 ) + 48 ;
298+ } else {
299+ let d1 = n << 1 ;
300+ curr -= 2 ;
301+ ptr:: copy_nonoverlapping( lut_ptr. offset( d1) , buf_ptr. offset( curr) , 2 ) ;
302+ }
303+ }
304+
305+ let buf_slice = unsafe {
306+ str :: from_utf8_unchecked(
307+ slice:: from_raw_parts( buf_ptr. offset( curr) , buf. len( ) - curr as usize ) )
308+ } ;
309+ f. pad_integral( is_positive, "" , buf_slice)
310+ }
311+ } ) * ) ;
312+ }
313+
314+ impl_Display ! ( i8 , u8 , i16 , u16 , i32 , u32 : to_u32) ;
315+ impl_Display ! ( i64 , u64 : to_u64) ;
316+ #[ cfg( target_pointer_width = "32" ) ]
317+ impl_Display ! ( isize , usize : to_u32) ;
318+ #[ cfg( target_pointer_width = "64" ) ]
319+ impl_Display ! ( isize , usize : to_u64) ;
0 commit comments