11//! Integer and floating-point number formatting 
22
3- // ignore-tidy-undocumented-unsafe 
4- 
53use  crate :: fmt; 
64use  crate :: mem:: MaybeUninit ; 
75use  crate :: num:: flt2dec; 
@@ -84,6 +82,8 @@ trait GenericRadix {
8482            } 
8583        } 
8684        let  buf = & buf[ curr..] ; 
85+         // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be 
86+         // valid UTF-8 
8787        let  buf = unsafe  { 
8888            str:: from_utf8_unchecked ( slice:: from_raw_parts ( MaybeUninit :: first_ptr ( buf) ,  buf. len ( ) ) ) 
8989        } ; 
@@ -189,11 +189,19 @@ static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
189189macro_rules!  impl_Display { 
190190    ( $( $t: ident) ,*  as  $u: ident via $conv_fn: ident named $name: ident)  => { 
191191        fn  $name( mut  n:  $u,  is_nonnegative:  bool ,  f:  & mut  fmt:: Formatter <' _>)  -> fmt:: Result  { 
192+             // 2^128 is about 3*10^38, so 39 gives an extra byte of space 
192193            let  mut  buf = [ MaybeUninit :: <u8 >:: uninit( ) ;  39 ] ; 
193194            let  mut  curr = buf. len( )  as  isize ; 
194195            let  buf_ptr = MaybeUninit :: first_ptr_mut( & mut  buf) ; 
195196            let  lut_ptr = DEC_DIGITS_LUT . as_ptr( ) ; 
196197
198+             // SAFETY: Since `d1` and `d2` are always less than or equal to `198`, we 
199+             // can copy from `lut_ptr[d1..d1 + 1]` and `lut_ptr[d2..d2 + 1]`. To show 
200+             // that it's OK to copy into `buf_ptr`, notice that at the beginning 
201+             // `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at 
202+             // each step this is kept the same as `n` is divided. Since `n` is always 
203+             // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]` 
204+             // is safe to access. 
197205            unsafe  { 
198206                // need at least 16 bits for the 4-characters-at-a-time to work. 
199207                assert!( crate :: mem:: size_of:: <$u>( )  >= 2 ) ; 
@@ -206,6 +214,10 @@ macro_rules! impl_Display {
206214                    let  d1 = ( rem / 100 )  << 1 ; 
207215                    let  d2 = ( rem % 100 )  << 1 ; 
208216                    curr -= 4 ; 
217+ 
218+                     // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since 
219+                     // otherwise `curr < 0`. But then `n` was originally at least `10000^10` 
220+                     // which is `10^40 > 2^128 > n`. 
209221                    ptr:: copy_nonoverlapping( lut_ptr. offset( d1) ,  buf_ptr. offset( curr) ,  2 ) ; 
210222                    ptr:: copy_nonoverlapping( lut_ptr. offset( d2) ,  buf_ptr. offset( curr + 2 ) ,  2 ) ; 
211223                } 
@@ -232,6 +244,8 @@ macro_rules! impl_Display {
232244                } 
233245            } 
234246
247+             // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid 
248+             // UTF-8 since `DEC_DIGITS_LUT` is 
235249            let  buf_slice = unsafe  { 
236250                str :: from_utf8_unchecked( 
237251                    slice:: from_raw_parts( buf_ptr. offset( curr) ,  buf. len( )  - curr as  usize ) ) 
@@ -304,6 +318,8 @@ macro_rules! impl_Exp {
304318            } ; 
305319
306320            // 39 digits (worst case u128) + . = 40 
321+             // Since `curr` always decreases by the number of digits copied, this means 
322+             // that `curr >= 0`. 
307323            let  mut  buf = [ MaybeUninit :: <u8 >:: uninit( ) ;  40 ] ; 
308324            let  mut  curr = buf. len( )  as  isize ;  //index for buf 
309325            let  buf_ptr = MaybeUninit :: first_ptr_mut( & mut  buf) ; 
@@ -313,6 +329,8 @@ macro_rules! impl_Exp {
313329            while  n >= 100  { 
314330                let  d1 = ( ( n % 100 )  as  isize )  << 1 ; 
315331                curr -= 2 ; 
332+                 // SAFETY: `d1 <= 198`, so we can copy from `lut_ptr[d1..d1 + 2]` since 
333+                 // `DEC_DIGITS_LUT` has a length of 200. 
316334                unsafe  { 
317335                    ptr:: copy_nonoverlapping( lut_ptr. offset( d1) ,  buf_ptr. offset( curr) ,  2 ) ; 
318336                } 
@@ -324,6 +342,7 @@ macro_rules! impl_Exp {
324342            // decode second-to-last character 
325343            if  n >= 10  { 
326344                curr -= 1 ; 
345+                 // SAFETY: Safe since `40 > curr >= 0` (see comment) 
327346                unsafe  { 
328347                    * buf_ptr. offset( curr)  = ( n as  u8  % 10_u8 )  + b'0' ; 
329348                } 
@@ -333,11 +352,13 @@ macro_rules! impl_Exp {
333352            // add decimal point iff >1 mantissa digit will be printed 
334353            if  exponent != trailing_zeros || added_precision != 0  { 
335354                curr -= 1 ; 
355+                 // SAFETY: Safe since `40 > curr >= 0` 
336356                unsafe  { 
337357                    * buf_ptr. offset( curr)  = b'.' ; 
338358                } 
339359            } 
340360
361+             // SAFETY: Safe since `40 > curr >= 0` 
341362            let  buf_slice = unsafe  { 
342363                // decode last character 
343364                curr -= 1 ; 
@@ -350,6 +371,8 @@ macro_rules! impl_Exp {
350371            // stores 'e' (or 'E') and the up to 2-digit exponent 
351372            let  mut  exp_buf = [ MaybeUninit :: <u8 >:: uninit( ) ;  3 ] ; 
352373            let  exp_ptr = MaybeUninit :: first_ptr_mut( & mut  exp_buf) ; 
374+             // SAFETY: In either case, `exp_buf` is written within bounds and `exp_ptr[..len]` 
375+             // is contained within `exp_buf` since `len <= 3`. 
353376            let  exp_slice = unsafe  { 
354377                * exp_ptr. offset( 0 )  = if  upper { b'E' }  else { b'e' } ; 
355378                let  len = if  exponent < 10  { 
0 commit comments