@@ -77,7 +77,13 @@ impl SuffixType {
7777/// Convert a number into a magnitude and a multi-byte unit suffix.
7878///
7979/// The returned string has a maximum length of 5 chars, for example: "1.1kB", "999kB", "1MB".
80- pub ( crate ) fn to_magnitude_and_suffix ( n : u128 , suffix_type : SuffixType ) -> String {
80+ /// `add_tracing_zero` allows to add tracing zero for values in 0 < x <= 9
81+ ///
82+ pub ( crate ) fn to_magnitude_and_suffix (
83+ n : u128 ,
84+ suffix_type : SuffixType ,
85+ add_tracing_zero : bool ,
86+ ) -> String {
8187 let bases = suffix_type. bases ( ) ;
8288 let suffixes = suffix_type. suffixes ( ) ;
8389 let mut i = 0 ;
@@ -91,14 +97,25 @@ pub(crate) fn to_magnitude_and_suffix(n: u128, suffix_type: SuffixType) -> Strin
9197 let suffix = suffixes[ i] ;
9298
9399 if rem == 0 {
94- format ! ( "{quot}{suffix}" )
100+ if add_tracing_zero && !suffix. is_empty ( ) && quot != 0 && quot <= 9 {
101+ format ! ( "{quot}.0{suffix}" )
102+ } else {
103+ format ! ( "{quot}{suffix}" )
104+ }
95105 } else {
96106 let tenths_place = rem / ( bases[ i] / 10 ) ;
97107
98- if rem % ( bases[ i] / 10 ) == 0 {
108+ if quot >= 100 && rem > 0 {
109+ format ! ( "{}{suffix}" , quot + 1 )
110+ } else if rem % ( bases[ i] / 10 ) == 0 {
99111 format ! ( "{quot}.{tenths_place}{suffix}" )
100112 } else if tenths_place + 1 == 10 || quot >= 10 {
101- format ! ( "{}{suffix}" , quot + 1 )
113+ let quot = quot + 1 ;
114+ if add_tracing_zero && !suffix. is_empty ( ) && quot <= 9 {
115+ format ! ( "{quot}.0{suffix}" )
116+ } else {
117+ format ! ( "{quot}{suffix}" )
118+ }
102119 } else {
103120 format ! ( "{quot}.{}{suffix}" , tenths_place + 1 )
104121 }
@@ -150,6 +167,18 @@ impl BlockSize {
150167 Self :: Bytes ( n) => n,
151168 }
152169 }
170+
171+ pub ( crate ) fn to_header ( & self ) -> String {
172+ match self {
173+ Self :: Bytes ( n) => {
174+ if n % 1024 == 0 && n % 1000 != 0 {
175+ to_magnitude_and_suffix ( * n as u128 , SuffixType :: Iec , false )
176+ } else {
177+ to_magnitude_and_suffix ( * n as u128 , SuffixType :: Si , false )
178+ }
179+ }
180+ }
181+ }
153182}
154183
155184impl Default for BlockSize {
@@ -196,9 +225,9 @@ impl fmt::Display for BlockSize {
196225 match self {
197226 Self :: Bytes ( n) => {
198227 let s = if n % 1024 == 0 && n % 1000 != 0 {
199- to_magnitude_and_suffix ( * n as u128 , SuffixType :: Iec )
228+ to_magnitude_and_suffix ( * n as u128 , SuffixType :: Iec , true )
200229 } else {
201- to_magnitude_and_suffix ( * n as u128 , SuffixType :: Si )
230+ to_magnitude_and_suffix ( * n as u128 , SuffixType :: Si , true )
202231 } ;
203232
204233 write ! ( f, "{s}" )
@@ -214,77 +243,168 @@ mod tests {
214243
215244 use crate :: blocks:: { BlockSize , SuffixType , to_magnitude_and_suffix} ;
216245
246+ #[ test]
247+ fn test_to_magnitude_and_suffix_rounding ( ) {
248+ assert_eq ! (
249+ to_magnitude_and_suffix( 999_440 , SuffixType :: Si , true ) ,
250+ "1.0MB"
251+ ) ;
252+ assert_eq ! (
253+ to_magnitude_and_suffix( 819_200 , SuffixType :: Si , true ) ,
254+ "820kB"
255+ ) ;
256+ assert_eq ! (
257+ to_magnitude_and_suffix( 819_936 , SuffixType :: Si , true ) ,
258+ "820kB"
259+ ) ;
260+ assert_eq ! (
261+ to_magnitude_and_suffix( 818_400 , SuffixType :: Si , true ) ,
262+ "819kB"
263+ ) ;
264+ assert_eq ! (
265+ to_magnitude_and_suffix( 817_600 , SuffixType :: Si , true ) ,
266+ "818kB"
267+ ) ;
268+ assert_eq ! (
269+ to_magnitude_and_suffix( 817_200 , SuffixType :: Si , true ) ,
270+ "818kB"
271+ ) ;
272+ }
273+
274+ #[ test]
275+ fn test_to_magnitude_and_suffix_add_tracing_zero ( ) {
276+ assert_eq ! ( to_magnitude_and_suffix( 1024 , SuffixType :: Iec , true ) , "1.0K" ) ;
277+ assert_eq ! ( to_magnitude_and_suffix( 2048 , SuffixType :: Iec , true ) , "2.0K" ) ;
278+ assert_eq ! ( to_magnitude_and_suffix( 10240 , SuffixType :: Iec , true ) , "10K" ) ;
279+
280+ assert_eq ! ( to_magnitude_and_suffix( 1024 , SuffixType :: Iec , false ) , "1K" ) ;
281+ assert_eq ! ( to_magnitude_and_suffix( 2048 , SuffixType :: Iec , false ) , "2K" ) ;
282+ assert_eq ! (
283+ to_magnitude_and_suffix( 10240 , SuffixType :: Iec , false ) ,
284+ "10K"
285+ ) ;
286+ }
287+
217288 #[ test]
218289 fn test_to_magnitude_and_suffix_powers_of_1024 ( ) {
219- assert_eq ! ( to_magnitude_and_suffix( 1024 , SuffixType :: Iec ) , "1K" ) ;
220- assert_eq ! ( to_magnitude_and_suffix( 2048 , SuffixType :: Iec ) , "2K" ) ;
221- assert_eq ! ( to_magnitude_and_suffix( 4096 , SuffixType :: Iec ) , "4K" ) ;
222- assert_eq ! ( to_magnitude_and_suffix( 1024 * 1024 , SuffixType :: Iec ) , "1M" ) ;
290+ assert_eq ! ( to_magnitude_and_suffix( 1024 , SuffixType :: Iec , false ) , "1K" ) ;
223291 assert_eq ! (
224- to_magnitude_and_suffix( 2 * 1024 * 1024 , SuffixType :: Iec ) ,
292+ to_magnitude_and_suffix( 10240 , SuffixType :: Iec , false ) ,
293+ "10K"
294+ ) ;
295+ assert_eq ! ( to_magnitude_and_suffix( 2048 , SuffixType :: Iec , false ) , "2K" ) ;
296+ assert_eq ! (
297+ to_magnitude_and_suffix( 1024 * 40 , SuffixType :: Iec , false ) ,
298+ "40K"
299+ ) ;
300+ assert_eq ! (
301+ to_magnitude_and_suffix( 1024 * 1024 , SuffixType :: Iec , false ) ,
302+ "1M"
303+ ) ;
304+ assert_eq ! (
305+ to_magnitude_and_suffix( 2 * 1024 * 1024 , SuffixType :: Iec , false ) ,
225306 "2M"
226307 ) ;
227308 assert_eq ! (
228- to_magnitude_and_suffix( 1024 * 1024 * 1024 , SuffixType :: Iec ) ,
309+ to_magnitude_and_suffix( 1024 * 1024 * 1024 , SuffixType :: Iec , false ) ,
229310 "1G"
230311 ) ;
231312 assert_eq ! (
232- to_magnitude_and_suffix( 34 * 1024 * 1024 * 1024 , SuffixType :: Iec ) ,
313+ to_magnitude_and_suffix( 34 * 1024 * 1024 * 1024 , SuffixType :: Iec , false ) ,
233314 "34G"
234315 ) ;
235316 }
236317
237318 #[ test]
238319 #[ allow( clippy:: cognitive_complexity) ]
239320 fn test_to_magnitude_and_suffix_not_powers_of_1024 ( ) {
240- assert_eq ! ( to_magnitude_and_suffix( 1 , SuffixType :: Si ) , "1B" ) ;
241- assert_eq ! ( to_magnitude_and_suffix( 999 , SuffixType :: Si ) , "999B" ) ;
242-
243- assert_eq ! ( to_magnitude_and_suffix( 1000 , SuffixType :: Si ) , "1kB" ) ;
244- assert_eq ! ( to_magnitude_and_suffix( 1001 , SuffixType :: Si ) , "1.1kB" ) ;
245- assert_eq ! ( to_magnitude_and_suffix( 1023 , SuffixType :: Si ) , "1.1kB" ) ;
246- assert_eq ! ( to_magnitude_and_suffix( 1025 , SuffixType :: Si ) , "1.1kB" ) ;
247- assert_eq ! ( to_magnitude_and_suffix( 10_001 , SuffixType :: Si ) , "11kB" ) ;
248- assert_eq ! ( to_magnitude_and_suffix( 999_000 , SuffixType :: Si ) , "999kB" ) ;
249-
250- assert_eq ! ( to_magnitude_and_suffix( 999_001 , SuffixType :: Si ) , "1MB" ) ;
251- assert_eq ! ( to_magnitude_and_suffix( 999_999 , SuffixType :: Si ) , "1MB" ) ;
252- assert_eq ! ( to_magnitude_and_suffix( 1_000_000 , SuffixType :: Si ) , "1MB" ) ;
253- assert_eq ! ( to_magnitude_and_suffix( 1_000_001 , SuffixType :: Si ) , "1.1MB" ) ;
254- assert_eq ! ( to_magnitude_and_suffix( 1_100_000 , SuffixType :: Si ) , "1.1MB" ) ;
255- assert_eq ! ( to_magnitude_and_suffix( 1_100_001 , SuffixType :: Si ) , "1.2MB" ) ;
256- assert_eq ! ( to_magnitude_and_suffix( 1_900_000 , SuffixType :: Si ) , "1.9MB" ) ;
257- assert_eq ! ( to_magnitude_and_suffix( 1_900_001 , SuffixType :: Si ) , "2MB" ) ;
258- assert_eq ! ( to_magnitude_and_suffix( 9_900_000 , SuffixType :: Si ) , "9.9MB" ) ;
259- assert_eq ! ( to_magnitude_and_suffix( 9_900_001 , SuffixType :: Si ) , "10MB" ) ;
321+ assert_eq ! ( to_magnitude_and_suffix( 1 , SuffixType :: Si , true ) , "1.0B" ) ;
322+ assert_eq ! ( to_magnitude_and_suffix( 999 , SuffixType :: Si , true ) , "999B" ) ;
323+
324+ assert_eq ! ( to_magnitude_and_suffix( 1000 , SuffixType :: Si , true ) , "1.0kB" ) ;
325+ assert_eq ! ( to_magnitude_and_suffix( 1001 , SuffixType :: Si , true ) , "1.1kB" ) ;
326+ assert_eq ! ( to_magnitude_and_suffix( 1023 , SuffixType :: Si , true ) , "1.1kB" ) ;
327+ assert_eq ! ( to_magnitude_and_suffix( 1025 , SuffixType :: Si , true ) , "1.1kB" ) ;
328+ assert_eq ! (
329+ to_magnitude_and_suffix( 10_001 , SuffixType :: Si , true ) ,
330+ "11kB"
331+ ) ;
332+ assert_eq ! (
333+ to_magnitude_and_suffix( 999_000 , SuffixType :: Si , true ) ,
334+ "999kB"
335+ ) ;
336+
337+ assert_eq ! (
338+ to_magnitude_and_suffix( 999_001 , SuffixType :: Si , true ) ,
339+ "1.0MB"
340+ ) ;
341+ assert_eq ! (
342+ to_magnitude_and_suffix( 999_999 , SuffixType :: Si , true ) ,
343+ "1.0MB"
344+ ) ;
345+ assert_eq ! (
346+ to_magnitude_and_suffix( 1_000_000 , SuffixType :: Si , true ) ,
347+ "1.0MB"
348+ ) ;
349+ assert_eq ! (
350+ to_magnitude_and_suffix( 1_000_001 , SuffixType :: Si , true ) ,
351+ "1.1MB"
352+ ) ;
353+ assert_eq ! (
354+ to_magnitude_and_suffix( 1_100_000 , SuffixType :: Si , true ) ,
355+ "1.1MB"
356+ ) ;
357+ assert_eq ! (
358+ to_magnitude_and_suffix( 1_100_001 , SuffixType :: Si , true ) ,
359+ "1.2MB"
360+ ) ;
361+ assert_eq ! (
362+ to_magnitude_and_suffix( 1_900_000 , SuffixType :: Si , true ) ,
363+ "1.9MB"
364+ ) ;
260365 assert_eq ! (
261- to_magnitude_and_suffix( 999_000_000 , SuffixType :: Si ) ,
366+ to_magnitude_and_suffix( 1_900_001 , SuffixType :: Si , true ) ,
367+ "2.0MB"
368+ ) ;
369+ assert_eq ! (
370+ to_magnitude_and_suffix( 9_900_000 , SuffixType :: Si , true ) ,
371+ "9.9MB"
372+ ) ;
373+ assert_eq ! (
374+ to_magnitude_and_suffix( 9_900_001 , SuffixType :: Si , true ) ,
375+ "10MB"
376+ ) ;
377+ assert_eq ! (
378+ to_magnitude_and_suffix( 999_000_000 , SuffixType :: Si , true ) ,
262379 "999MB"
263380 ) ;
264381
265- assert_eq ! ( to_magnitude_and_suffix( 999_000_001 , SuffixType :: Si ) , "1GB" ) ;
266382 assert_eq ! (
267- to_magnitude_and_suffix( 1_000_000_000 , SuffixType :: Si ) ,
268- "1GB"
383+ to_magnitude_and_suffix( 999_000_001 , SuffixType :: Si , true ) ,
384+ "1.0GB"
385+ ) ;
386+ assert_eq ! (
387+ to_magnitude_and_suffix( 1_000_000_000 , SuffixType :: Si , true ) ,
388+ "1.0GB"
269389 ) ;
270390 assert_eq ! (
271- to_magnitude_and_suffix( 1_000_000_001 , SuffixType :: Si ) ,
391+ to_magnitude_and_suffix( 1_000_000_001 , SuffixType :: Si , true ) ,
272392 "1.1GB"
273393 ) ;
274394 }
275395
276396 #[ test]
277397 fn test_block_size_display ( ) {
278- assert_eq ! ( format!( "{}" , BlockSize :: Bytes ( 1024 ) ) , "1K " ) ;
279- assert_eq ! ( format!( "{}" , BlockSize :: Bytes ( 2 * 1024 ) ) , "2K " ) ;
280- assert_eq ! ( format!( "{}" , BlockSize :: Bytes ( 3 * 1024 * 1024 ) ) , "3M " ) ;
398+ assert_eq ! ( format!( "{}" , BlockSize :: Bytes ( 1024 ) ) , "1.0K " ) ;
399+ assert_eq ! ( format!( "{}" , BlockSize :: Bytes ( 2 * 1024 ) ) , "2.0K " ) ;
400+ assert_eq ! ( format!( "{}" , BlockSize :: Bytes ( 3 * 1024 * 1024 ) ) , "3.0M " ) ;
281401 }
282402
283403 #[ test]
284404 fn test_block_size_display_multiples_of_1000_and_1024 ( ) {
285405 assert_eq ! ( format!( "{}" , BlockSize :: Bytes ( 128_000 ) ) , "128kB" ) ;
286406 assert_eq ! ( format!( "{}" , BlockSize :: Bytes ( 1000 * 1024 ) ) , "1.1MB" ) ;
287- assert_eq ! ( format!( "{}" , BlockSize :: Bytes ( 1_000_000_000_000 ) ) , "1TB " ) ;
407+ assert_eq ! ( format!( "{}" , BlockSize :: Bytes ( 1_000_000_000_000 ) ) , "1.0TB " ) ;
288408 }
289409
290410 #[ test]
0 commit comments