11use super :: super :: units:: { BinPrefix , PrefixKind , SiPrefix , UnitPrefix } ;
22use filesize:: PathExt ;
33use std:: {
4+ cell:: { Ref , RefCell } ,
45 fmt:: { self , Display } ,
56 fs:: Metadata ,
67 path:: Path ,
@@ -14,6 +15,11 @@ pub struct Metric {
1415 #[ allow( dead_code) ]
1516 kind : MetricKind ,
1617 prefix_kind : PrefixKind ,
18+
19+ /// To prevent allocating the same string twice. We allocate the first time
20+ /// in [`crate::tree::update_column_properties`] in order to compute the max column width for
21+ /// human-readable size and the second time during the actual render.
22+ cached_display : RefCell < String > ,
1723}
1824
1925/// Represents the appropriate method in which to compute bytes. `Logical` represent the total amount
@@ -39,26 +45,29 @@ impl Metric {
3945 human_readable,
4046 kind,
4147 prefix_kind,
48+ cached_display : RefCell :: default ( ) ,
4249 }
4350 }
4451
4552 /// Initializes an empty [Metric] used to represent the total amount of bytes of a file.
46- pub const fn init_empty_logical ( human_readable : bool , prefix_kind : PrefixKind ) -> Self {
53+ pub fn init_empty_logical ( human_readable : bool , prefix_kind : PrefixKind ) -> Self {
4754 Self {
4855 value : 0 ,
4956 human_readable,
5057 kind : MetricKind :: Logical ,
5158 prefix_kind,
59+ cached_display : RefCell :: default ( ) ,
5260 }
5361 }
5462
5563 /// Initializes an empty [Metric] used to represent the total disk space of a file in bytes.
56- pub const fn init_empty_physical ( human_readable : bool , prefix_kind : PrefixKind ) -> Self {
64+ pub fn init_empty_physical ( human_readable : bool , prefix_kind : PrefixKind ) -> Self {
5765 Self {
5866 value : 0 ,
5967 human_readable,
6068 kind : MetricKind :: Physical ,
6169 prefix_kind,
70+ cached_display : RefCell :: default ( ) ,
6271 }
6372 }
6473
@@ -77,46 +86,66 @@ impl Metric {
7786 human_readable,
7887 kind,
7988 prefix_kind,
89+ cached_display : RefCell :: default ( ) ,
8090 }
8191 }
92+
93+ /// Returns an immutable borrow of the `cached_display`.
94+ pub fn cached_display ( & self ) -> Ref < ' _ , String > {
95+ self . cached_display . borrow ( )
96+ }
8297}
8398
8499impl Display for Metric {
85100 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
86- let value = self . value as f64 ;
101+ {
102+ let cached_display = self . cached_display ( ) ;
87103
88- match self . prefix_kind {
89- PrefixKind :: Si => {
90- if !self . human_readable {
91- return write ! ( f, "{} {}" , self . value, SiPrefix :: Base ) ;
92- }
104+ if cached_display. len ( ) > 0 {
105+ return write ! ( f, "{cached_display}" ) ;
106+ }
107+ }
93108
94- let unit = SiPrefix :: from ( self . value ) ;
109+ let value = self . value as f64 ;
95110
96- if matches ! ( unit, SiPrefix :: Base ) {
97- write ! ( f, "{} {unit}" , self . value)
111+ let display = match self . prefix_kind {
112+ PrefixKind :: Si => {
113+ if self . human_readable {
114+ let unit = SiPrefix :: from ( self . value ) ;
115+
116+ if matches ! ( unit, SiPrefix :: Base ) {
117+ format ! ( "{} {unit}" , self . value)
118+ } else {
119+ let base_value = unit. base_value ( ) ;
120+ let size = value / ( base_value as f64 ) ;
121+ format ! ( "{size:.1} {unit}" )
122+ }
98123 } else {
99- let base_value = unit. base_value ( ) ;
100- let size = value / ( base_value as f64 ) ;
101- write ! ( f, "{size:.2} {unit}" )
124+ format ! ( "{} {}" , self . value, SiPrefix :: Base )
102125 }
103126 }
104127 PrefixKind :: Bin => {
105- if !self . human_readable {
106- return write ! ( f, "{} {}" , self . value, BinPrefix :: Base ) ;
107- }
108-
109- let unit = BinPrefix :: from ( self . value ) ;
110-
111- if matches ! ( unit, BinPrefix :: Base ) {
112- write ! ( f, "{} {unit}" , self . value)
128+ if self . human_readable {
129+ let unit = BinPrefix :: from ( self . value ) ;
130+
131+ if matches ! ( unit, BinPrefix :: Base ) {
132+ format ! ( "{} {unit}" , self . value)
133+ } else {
134+ let base_value = unit. base_value ( ) ;
135+ let size = value / ( base_value as f64 ) ;
136+ format ! ( "{size:.1} {unit}" )
137+ }
113138 } else {
114- let base_value = unit. base_value ( ) ;
115- let size = value / ( base_value as f64 ) ;
116- write ! ( f, "{size:.2} {unit}" )
139+ format ! ( "{} {}" , self . value, BinPrefix :: Base )
117140 }
118141 }
119- }
142+ } ;
143+
144+ write ! ( f, "{display}" ) ?;
145+
146+ self . cached_display . replace ( display) ;
147+
148+ Ok ( ( ) )
120149 }
121150}
122151
@@ -127,6 +156,7 @@ fn test_metric() {
127156 kind : MetricKind :: Logical ,
128157 human_readable : false ,
129158 prefix_kind : PrefixKind :: Bin ,
159+ cached_display : RefCell :: < String > :: default ( ) ,
130160 } ;
131161 assert_eq ! ( format!( "{}" , metric) , "100 B" ) ;
132162
@@ -135,14 +165,16 @@ fn test_metric() {
135165 kind : MetricKind :: Logical ,
136166 human_readable : true ,
137167 prefix_kind : PrefixKind :: Si ,
168+ cached_display : RefCell :: < String > :: default ( ) ,
138169 } ;
139- assert_eq ! ( format!( "{}" , metric) , "1.00 KB" ) ;
170+ assert_eq ! ( format!( "{}" , metric) , "1.0 KB" ) ;
140171
141172 let metric = Metric {
142173 value : 1000 ,
143174 kind : MetricKind :: Logical ,
144175 human_readable : true ,
145176 prefix_kind : PrefixKind :: Bin ,
177+ cached_display : RefCell :: < String > :: default ( ) ,
146178 } ;
147179 assert_eq ! ( format!( "{}" , metric) , "1000 B" ) ;
148180
@@ -151,22 +183,25 @@ fn test_metric() {
151183 kind : MetricKind :: Logical ,
152184 human_readable : true ,
153185 prefix_kind : PrefixKind :: Bin ,
186+ cached_display : RefCell :: < String > :: default ( ) ,
154187 } ;
155- assert_eq ! ( format!( "{}" , metric) , "1.00 KiB" ) ;
188+ assert_eq ! ( format!( "{}" , metric) , "1.0 KiB" ) ;
156189
157190 let metric = Metric {
158191 value : 2_u64 . pow ( 20 ) ,
159192 kind : MetricKind :: Logical ,
160193 human_readable : true ,
161194 prefix_kind : PrefixKind :: Bin ,
195+ cached_display : RefCell :: < String > :: default ( ) ,
162196 } ;
163- assert_eq ! ( format!( "{}" , metric) , "1.00 MiB" ) ;
197+ assert_eq ! ( format!( "{}" , metric) , "1.0 MiB" ) ;
164198
165199 let metric = Metric {
166200 value : 123454 ,
167201 kind : MetricKind :: Logical ,
168202 human_readable : false ,
169203 prefix_kind : PrefixKind :: Bin ,
204+ cached_display : RefCell :: < String > :: default ( ) ,
170205 } ;
171206 assert_eq ! ( format!( "{}" , metric) , "123454 B" ) ;
172207}
0 commit comments