@@ -457,31 +457,33 @@ fn construct_committed_str(mem_info: &MemInfo, n2s: &dyn Fn(u64) -> String) -> S
457457}
458458
459459// Here's the `-h` `--human` flag processing logic
460+ // See: https://github.com/uutils/procps/pull/431
460461fn humanized ( kib : u64 , si : bool ) -> String {
461- let binding = {
462- let display = ByteSize :: kib ( kib) . display ( ) ;
463-
464- if si {
465- display. si ( )
466- } else {
467- display. iec ( )
468- }
462+ let b = ByteSize :: kib ( kib) . 0 ;
463+ let units = [ 'B' , 'K' , 'M' , 'G' , 'T' , 'P' ] ;
464+ let mut level = 0 ;
465+ let mut divisor = 1 ;
466+ while level < units. len ( ) - 1 && divisor * 100 <= b {
467+ divisor *= if si { 1000 } else { 1024 } ;
468+ level += 1 ;
469+ }
470+ if level == 0 {
471+ return format ! ( "{}{}" , b, units[ level] ) ;
469472 }
470- . to_string ( ) ;
471-
472- let split: Vec < & str > = binding. split ( ' ' ) . collect ( ) ;
473-
474- // TODO: finish the logic of automatic scale.
475- let num_string = String :: from ( split[ 0 ] ) ;
476473
477- let unit_string = {
478- let mut tmp = String :: from ( split[ 1 ] ) ;
479- if tmp != "B" {
480- tmp. pop ( ) ;
481- }
482- tmp
474+ let value = ( b as f64 ) / ( divisor as f64 ) ;
475+ let formatted_value = if ( value * 10.0 ) . round ( ) < 100.0 {
476+ format ! ( "{:.1}" , ( value * 10.0 ) . round( ) / 10.0 )
477+ } else {
478+ ( value as u64 ) . to_string ( )
483479 } ;
484- format ! ( "{}{}" , num_string, unit_string)
480+
481+ format ! (
482+ "{}{}{}" ,
483+ formatted_value,
484+ units[ level] . to_owned( ) ,
485+ if si { "" } else { "i" }
486+ )
485487}
486488
487489fn detect_unit ( arg : & ArgMatches ) -> fn ( u64 ) -> u64 {
@@ -541,8 +543,22 @@ mod test {
541543 }
542544
543545 #[ test]
544- fn test_humanized_unit_for_zero ( ) {
545- assert_eq ! ( "0B" , humanized( 0 , false ) ) ;
546- assert_eq ! ( "0B" , humanized( 0 , true ) ) ;
546+ fn test_humanized_unit ( ) {
547+ let test_cases = [
548+ ( 0 , false , "0B" ) ,
549+ ( 0 , true , "0B" ) ,
550+ ( 1023 , false , "1.0Mi" ) ,
551+ ( 1024 , true , "1.0M" ) ,
552+ ( 1024 , false , "1.0Mi" ) ,
553+ ( 1536 , true , "1.6M" ) ,
554+ ( 1536 , false , "1.5Mi" ) ,
555+ ( 8500 , true , "8.7M" ) ,
556+ ( 8500 , false , "8.3Mi" ) ,
557+ ( 10138 , false , "9.9Mi" ) ,
558+ ( 10230 , false , "9Mi" ) ,
559+ ] ;
560+ for & ( kib, si, expected) in & test_cases {
561+ assert_eq ! ( humanized( kib, si) , expected) ;
562+ }
547563 }
548564}
0 commit comments