@@ -13,6 +13,23 @@ pub enum AssetCapacity {
1313 Discrete ( u32 , Capacity ) ,
1414}
1515
16+ impl AssetCapacity {
17+ /// Return the smaller of `self` or `other`.
18+ ///
19+ /// # Panics
20+ ///
21+ /// Panics if the comparison is not meaningful. This happens if either `AssetCapacity` contains
22+ /// a NaN value, one is discrete and the other continuous or if both are discrete and the unit
23+ /// size differs.
24+ pub fn min ( self , other : AssetCapacity ) -> AssetCapacity {
25+ match self . partial_cmp ( & other) {
26+ None => panic ! ( "Comparing invalid AssetCapacity values ({self:?} and {other:?})" ) ,
27+ Some ( Ordering :: Greater ) => other,
28+ _ => self ,
29+ }
30+ }
31+ }
32+
1633impl Add for AssetCapacity {
1734 type Output = Self ;
1835
@@ -49,23 +66,15 @@ impl Sub for AssetCapacity {
4966 }
5067}
5168
52- impl Eq for AssetCapacity { }
53-
5469impl PartialOrd for AssetCapacity {
5570 fn partial_cmp ( & self , other : & Self ) -> Option < Ordering > {
56- Some ( self . cmp ( other) )
57- }
58- }
59-
60- impl Ord for AssetCapacity {
61- fn cmp ( & self , other : & Self ) -> Ordering {
6271 match ( self , other) {
63- ( AssetCapacity :: Continuous ( a) , AssetCapacity :: Continuous ( b) ) => a. total_cmp ( b) ,
72+ ( AssetCapacity :: Continuous ( a) , AssetCapacity :: Continuous ( b) ) => a. partial_cmp ( b) ,
6473 ( AssetCapacity :: Discrete ( units1, size1) , AssetCapacity :: Discrete ( units2, size2) ) => {
65- Self :: check_same_unit_size ( * size1 , * size2 ) ;
66- units1. cmp ( units2)
74+ // NB: Also returns `None` if either is NaN
75+ ( * size1 == * size2 ) . then ( || units1. cmp ( units2) )
6776 }
68- _ => panic ! ( "Cannot compare different types of AssetCapacity ({self:?} and {other:?})" ) ,
77+ _ => None ,
6978 }
7079 }
7180}
@@ -213,4 +222,111 @@ mod tests {
213222 let got = orig. apply_limit_factor ( factor) ;
214223 assert_eq ! ( got, AssetCapacity :: Discrete ( expected_units, unit_size) ) ;
215224 }
225+
226+ #[ rstest]
227+ #[ case:: less(
228+ AssetCapacity :: Continuous ( Capacity ( 4.0 ) ) ,
229+ AssetCapacity :: Continuous ( Capacity ( 6.0 ) ) ,
230+ Some ( Ordering :: Less )
231+ ) ]
232+ #[ case:: equal(
233+ AssetCapacity :: Continuous ( Capacity ( 4.0 ) ) ,
234+ AssetCapacity :: Continuous ( Capacity ( 4.0 ) ) ,
235+ Some ( Ordering :: Equal )
236+ ) ]
237+ #[ case:: greater(
238+ AssetCapacity :: Continuous ( Capacity ( 6.0 ) ) ,
239+ AssetCapacity :: Continuous ( Capacity ( 4.0 ) ) ,
240+ Some ( Ordering :: Greater )
241+ ) ]
242+ fn partial_cmp_continuous (
243+ #[ case] left : AssetCapacity ,
244+ #[ case] right : AssetCapacity ,
245+ #[ case] expected : Option < Ordering > ,
246+ ) {
247+ assert_eq ! ( left. partial_cmp( & right) , expected) ;
248+ assert_eq ! ( left == right, expected == Some ( Ordering :: Equal ) ) ;
249+ }
250+
251+ #[ rstest]
252+ #[ case:: less(
253+ AssetCapacity :: Discrete ( 2 , Capacity ( 3.0 ) ) ,
254+ AssetCapacity :: Discrete ( 4 , Capacity ( 3.0 ) ) ,
255+ Some ( Ordering :: Less )
256+ ) ]
257+ #[ case:: equal(
258+ AssetCapacity :: Discrete ( 4 , Capacity ( 3.0 ) ) ,
259+ AssetCapacity :: Discrete ( 4 , Capacity ( 3.0 ) ) ,
260+ Some ( Ordering :: Equal )
261+ ) ]
262+ #[ case:: greater(
263+ AssetCapacity :: Discrete ( 5 , Capacity ( 3.0 ) ) ,
264+ AssetCapacity :: Discrete ( 4 , Capacity ( 3.0 ) ) ,
265+ Some ( Ordering :: Greater )
266+ ) ]
267+ fn partial_cmp_discrete_with_matching_unit_size (
268+ #[ case] left : AssetCapacity ,
269+ #[ case] right : AssetCapacity ,
270+ #[ case] expected : Option < Ordering > ,
271+ ) {
272+ assert_eq ! ( left. partial_cmp( & right) , expected) ;
273+ assert_eq ! ( left == right, expected == Some ( Ordering :: Equal ) ) ;
274+ }
275+
276+ #[ rstest]
277+ #[ case:: mixed_types(
278+ AssetCapacity :: Continuous ( Capacity ( 4.0 ) ) ,
279+ AssetCapacity :: Discrete ( 4 , Capacity ( 1.0 ) )
280+ ) ]
281+ #[ case:: different_unit_sizes(
282+ AssetCapacity :: Discrete ( 4 , Capacity ( 1.0 ) ) ,
283+ AssetCapacity :: Discrete ( 4 , Capacity ( 2.0 ) )
284+ ) ]
285+ #[ case:: nan_continuous(
286+ AssetCapacity :: Continuous ( Capacity ( f64 :: NAN ) ) ,
287+ AssetCapacity :: Continuous ( Capacity ( 4.0 ) )
288+ ) ]
289+ fn partial_cmp_returns_none_for_invalid_comparisons (
290+ #[ case] left : AssetCapacity ,
291+ #[ case] right : AssetCapacity ,
292+ ) {
293+ assert_eq ! ( left. partial_cmp( & right) , None ) ;
294+ assert ! ( left != right) ;
295+ }
296+
297+ #[ rstest]
298+ #[ case:: continuous(
299+ AssetCapacity :: Continuous ( Capacity ( 4.0 ) ) ,
300+ AssetCapacity :: Continuous ( Capacity ( 6.0 ) ) ,
301+ AssetCapacity :: Continuous ( Capacity ( 4.0 ) )
302+ ) ]
303+ #[ case:: discrete(
304+ AssetCapacity :: Discrete ( 2 , Capacity ( 3.0 ) ) ,
305+ AssetCapacity :: Discrete ( 4 , Capacity ( 3.0 ) ) ,
306+ AssetCapacity :: Discrete ( 2 , Capacity ( 3.0 ) )
307+ ) ]
308+ fn min_returns_smaller_capacity (
309+ #[ case] left : AssetCapacity ,
310+ #[ case] right : AssetCapacity ,
311+ #[ case] expected : AssetCapacity ,
312+ ) {
313+ assert_eq ! ( left. min( right) , expected) ;
314+ }
315+
316+ #[ rstest]
317+ #[ case:: mixed_types(
318+ AssetCapacity :: Continuous ( Capacity ( 4.0 ) ) ,
319+ AssetCapacity :: Discrete ( 4 , Capacity ( 1.0 ) )
320+ ) ]
321+ #[ case:: different_unit_sizes(
322+ AssetCapacity :: Discrete ( 4 , Capacity ( 1.0 ) ) ,
323+ AssetCapacity :: Discrete ( 4 , Capacity ( 2.0 ) )
324+ ) ]
325+ #[ should_panic( expected = "Comparing invalid AssetCapacity values" ) ]
326+ fn min_panics_for_invalid_comparisons (
327+ #[ case] left : AssetCapacity ,
328+ #[ case] right : AssetCapacity ,
329+ ) {
330+ let _ = left. min ( right) ;
331+ }
216332}
0 commit comments