@@ -31,6 +31,20 @@ pub enum ParseQuantityError {
31
31
InvalidSuffix { source : ParseSuffixError } ,
32
32
}
33
33
34
+ // pub struct CpuQuant(Quantity1<DecimalMultiple>);
35
+
36
+ // pub struct Quantity1<T>
37
+ // where
38
+ // T: SuffixTrait,
39
+ // {
40
+ // value: f64,
41
+ // suffix: T,
42
+ // }
43
+
44
+ // pub trait SuffixTrait: FromStr + Default {
45
+ // fn factor(&self) -> f64;
46
+ // }
47
+
34
48
/// Quantity is a representation of a number with a suffix / format.
35
49
///
36
50
/// This type makes it possible to parse Kubernetes quantity strings like '12Ki', '2M, '1.5e2', or
@@ -208,6 +222,28 @@ impl Quantity {
208
222
}
209
223
}
210
224
225
+ pub fn scale_to_non_zero ( self ) -> Self {
226
+ if !self . value . between ( -1.0 , 1.0 ) {
227
+ return self ;
228
+ }
229
+
230
+ let mut this = self ;
231
+
232
+ while let Some ( suffix) = this. suffix . scale_down ( ) {
233
+ this = self . scale_to ( suffix) ;
234
+ if this. value . between ( -1.0 , 1.0 ) {
235
+ continue ;
236
+ } else {
237
+ return this;
238
+ }
239
+ }
240
+
241
+ Self {
242
+ value : 1.0 ,
243
+ suffix : this. suffix ,
244
+ }
245
+ }
246
+
211
247
/// Either sets the suffix of `self` to `rhs` or scales `rhs` if `self` has a value other than
212
248
/// zero.
213
249
///
@@ -228,46 +264,54 @@ impl Quantity {
228
264
}
229
265
}
230
266
267
+ trait FloatExt : PartialOrd + Sized {
268
+ fn between ( self , start : Self , end : Self ) -> bool {
269
+ self > start && self < end
270
+ }
271
+ }
272
+
273
+ impl FloatExt for f64 { }
274
+
231
275
#[ cfg( test) ]
232
276
mod test {
233
277
use super :: * ;
234
278
use rstest:: rstest;
235
279
280
+ // See https://github.com/kubernetes/apimachinery/blob/3e8e52d6a1259ada73f63c1c7d1fad39d4ba9fb4/pkg/api/resource/quantity_test.go#L276-L287
281
+ #[ rustfmt:: skip]
236
282
#[ rstest]
237
- #[ case( "49041204Ki" , Quantity { value: 49041204.0 , suffix: Suffix :: BinaryMultiple ( BinaryMultiple :: Kibi ) } ) ]
238
- #[ case( "256Ki" , Quantity { value: 256.0 , suffix: Suffix :: BinaryMultiple ( BinaryMultiple :: Kibi ) } ) ]
239
- #[ case( "1.5Gi" , Quantity { value: 1.5 , suffix: Suffix :: BinaryMultiple ( BinaryMultiple :: Gibi ) } ) ]
240
- #[ case( "0.8Ti" , Quantity { value: 0.8 , suffix: Suffix :: BinaryMultiple ( BinaryMultiple :: Tebi ) } ) ]
241
- #[ case( "3.2Pi" , Quantity { value: 3.2 , suffix: Suffix :: BinaryMultiple ( BinaryMultiple :: Pebi ) } ) ]
242
- #[ case( "0.2Ei" , Quantity { value: 0.2 , suffix: Suffix :: BinaryMultiple ( BinaryMultiple :: Exbi ) } ) ]
243
- #[ case( "8Mi" , Quantity { value: 8.0 , suffix: Suffix :: BinaryMultiple ( BinaryMultiple :: Mebi ) } ) ]
244
- fn binary_quantity_from_str_pass ( #[ case] input : & str , #[ case] expected : Quantity ) {
283
+ #[ case( "0" , 0.0 , Suffix :: DecimalMultiple ( DecimalMultiple :: Empty ) ) ]
284
+ #[ case( "0n" , 0.0 , Suffix :: DecimalMultiple ( DecimalMultiple :: Nano ) ) ]
285
+ #[ case( "0u" , 0.0 , Suffix :: DecimalMultiple ( DecimalMultiple :: Micro ) ) ]
286
+ #[ case( "0m" , 0.0 , Suffix :: DecimalMultiple ( DecimalMultiple :: Milli ) ) ]
287
+ #[ case( "0Ki" , 0.0 , Suffix :: BinaryMultiple ( BinaryMultiple :: Kibi ) ) ]
288
+ #[ case( "0k" , 0.0 , Suffix :: DecimalMultiple ( DecimalMultiple :: Kilo ) ) ]
289
+ #[ case( "0Mi" , 0.0 , Suffix :: BinaryMultiple ( BinaryMultiple :: Mebi ) ) ]
290
+ #[ case( "0M" , 0.0 , Suffix :: DecimalMultiple ( DecimalMultiple :: Mega ) ) ]
291
+ #[ case( "0Gi" , 0.0 , Suffix :: BinaryMultiple ( BinaryMultiple :: Gibi ) ) ]
292
+ #[ case( "0G" , 0.0 , Suffix :: DecimalMultiple ( DecimalMultiple :: Giga ) ) ]
293
+ #[ case( "0Ti" , 0.0 , Suffix :: BinaryMultiple ( BinaryMultiple :: Tebi ) ) ]
294
+ #[ case( "0T" , 0.0 , Suffix :: DecimalMultiple ( DecimalMultiple :: Tera ) ) ]
295
+ #[ case( "0Pi" , 0.0 , Suffix :: BinaryMultiple ( BinaryMultiple :: Pebi ) ) ]
296
+ #[ case( "0P" , 0.0 , Suffix :: DecimalMultiple ( DecimalMultiple :: Peta ) ) ]
297
+ #[ case( "0Ei" , 0.0 , Suffix :: BinaryMultiple ( BinaryMultiple :: Exbi ) ) ]
298
+ #[ case( "0E" , 0.0 , Suffix :: DecimalMultiple ( DecimalMultiple :: Exa ) ) ]
299
+ fn parse_zero_quantity ( #[ case] input : & str , #[ case] expected_value : f64 , #[ case] expected_suffix : Suffix ) {
245
300
let parsed = Quantity :: from_str ( input) . unwrap ( ) ;
246
- assert_eq ! ( parsed, expected) ;
247
- }
248
301
249
- #[ rstest]
250
- #[ case( "49041204k" , Quantity { value: 49041204.0 , suffix: Suffix :: DecimalMultiple ( DecimalMultiple :: Kilo ) } ) ]
251
- #[ case( "256k" , Quantity { value: 256.0 , suffix: Suffix :: DecimalMultiple ( DecimalMultiple :: Kilo ) } ) ]
252
- #[ case( "1.5G" , Quantity { value: 1.5 , suffix: Suffix :: DecimalMultiple ( DecimalMultiple :: Giga ) } ) ]
253
- #[ case( "0.8T" , Quantity { value: 0.8 , suffix: Suffix :: DecimalMultiple ( DecimalMultiple :: Tera ) } ) ]
254
- #[ case( "3.2P" , Quantity { value: 3.2 , suffix: Suffix :: DecimalMultiple ( DecimalMultiple :: Peta ) } ) ]
255
- #[ case( "0.2E" , Quantity { value: 0.2 , suffix: Suffix :: DecimalMultiple ( DecimalMultiple :: Exa ) } ) ]
256
- #[ case( "4m" , Quantity { value: 4.0 , suffix: Suffix :: DecimalMultiple ( DecimalMultiple :: Milli ) } ) ]
257
- #[ case( "8M" , Quantity { value: 8.0 , suffix: Suffix :: DecimalMultiple ( DecimalMultiple :: Mega ) } ) ]
258
- fn decimal_quantity_from_str_pass ( #[ case] input : & str , #[ case] expected : Quantity ) {
259
- let parsed = Quantity :: from_str ( input) . unwrap ( ) ;
260
- assert_eq ! ( parsed, expected) ;
302
+ assert_eq ! ( parsed. suffix, expected_suffix) ;
303
+ assert_eq ! ( parsed. value, expected_value) ;
261
304
}
262
305
306
+ // See https://github.com/kubernetes/apimachinery/blob/3e8e52d6a1259ada73f63c1c7d1fad39d4ba9fb4/pkg/api/resource/quantity_test.go#L289
307
+ #[ rustfmt:: skip]
263
308
#[ rstest]
264
- #[ case( "1.234e-3.21" , Quantity { value: 1.234 , suffix: Suffix :: DecimalExponent ( DecimalExponent :: from( -3.21 ) ) } ) ]
265
- #[ case( "1.234E-3.21" , Quantity { value: 1.234 , suffix: Suffix :: DecimalExponent ( DecimalExponent :: from( -3.21 ) ) } ) ]
266
- #[ case( "1.234e3" , Quantity { value: 1.234 , suffix: Suffix :: DecimalExponent ( DecimalExponent :: from( 3.0 ) ) } ) ]
267
- #[ case( "1.234E3" , Quantity { value: 1.234 , suffix: Suffix :: DecimalExponent ( DecimalExponent :: from( 3.0 ) ) } ) ]
268
- fn decimal_exponent_quantity_from_str_pass ( #[ case] input : & str , #[ case] expected : Quantity ) {
309
+ #[ case( "12.34" , 12.34 ) ]
310
+ #[ case( "12" , 12.0 ) ]
311
+ #[ case( "1" , 1.0 ) ]
312
+ fn parse_quantity_without_suffix ( #[ case] input : & str , #[ case] expected_value : f64 ) {
269
313
let parsed = Quantity :: from_str ( input) . unwrap ( ) ;
270
- assert_eq ! ( parsed, expected ) ;
314
+ assert_eq ! ( parsed. value , expected_value ) ;
271
315
}
272
316
273
317
#[ rstest]
0 commit comments