@@ -5,7 +5,7 @@ use crate::content::Content;
5
5
6
6
use serde:: { ser, Serialize , Serializer } ;
7
7
8
- #[ derive( PartialEq , PartialOrd , Debug ) ]
8
+ #[ derive( PartialEq , Debug ) ]
9
9
pub enum Key < ' a > {
10
10
Bool ( bool ) ,
11
11
U64 ( u64 ) ,
@@ -18,17 +18,61 @@ pub enum Key<'a> {
18
18
Other ,
19
19
}
20
20
21
+ impl < ' a > Key < ' a > {
22
+ /// Needed because std::mem::discriminant is not Ord
23
+ fn discriminant ( & self ) -> usize {
24
+ match self {
25
+ Key :: Bool ( _) => 1 ,
26
+ Key :: U64 ( _) => 2 ,
27
+ Key :: I64 ( _) => 3 ,
28
+ Key :: F64 ( _) => 4 ,
29
+ Key :: U128 ( _) => 5 ,
30
+ Key :: I128 ( _) => 6 ,
31
+ Key :: Str ( _) => 7 ,
32
+ Key :: Bytes ( _) => 8 ,
33
+ Key :: Other => 9 ,
34
+ }
35
+ }
36
+ }
37
+
21
38
impl < ' a > Eq for Key < ' a > { }
22
39
23
- // We're making a deliberate choice to just "round down" here, so ignoring the
24
- // clippy lint
25
- #[ allow( clippy:: derive_ord_xor_partial_ord) ]
26
40
impl < ' a > Ord for Key < ' a > {
27
41
fn cmp ( & self , other : & Self ) -> Ordering {
28
- self . partial_cmp ( other) . unwrap_or ( Ordering :: Less )
42
+ let self_discriminant = self . discriminant ( ) ;
43
+ let other_discriminant = other. discriminant ( ) ;
44
+ match Ord :: cmp ( & self_discriminant, & other_discriminant) {
45
+ Ordering :: Equal => match ( self , other) {
46
+ ( Key :: Bool ( a) , Key :: Bool ( b) ) => Ord :: cmp ( a, b) ,
47
+ ( Key :: U64 ( a) , Key :: U64 ( b) ) => Ord :: cmp ( a, b) ,
48
+ ( Key :: I64 ( a) , Key :: I64 ( b) ) => Ord :: cmp ( a, b) ,
49
+ ( Key :: F64 ( a) , Key :: F64 ( b) ) => f64_total_cmp ( * a, * b) ,
50
+ ( Key :: U128 ( a) , Key :: U128 ( b) ) => Ord :: cmp ( a, b) ,
51
+ ( Key :: I128 ( a) , Key :: I128 ( b) ) => Ord :: cmp ( a, b) ,
52
+ ( Key :: Str ( a) , Key :: Str ( b) ) => Ord :: cmp ( a, b) ,
53
+ ( Key :: Bytes ( a) , Key :: Bytes ( b) ) => Ord :: cmp ( a, b) ,
54
+ _ => Ordering :: Equal ,
55
+ } ,
56
+ cmp => cmp,
57
+ }
29
58
}
30
59
}
31
60
61
+ impl < ' a > PartialOrd for Key < ' a > {
62
+ fn partial_cmp ( & self , other : & Self ) -> Option < Ordering > {
63
+ Some ( self . cmp ( other) )
64
+ }
65
+ }
66
+
67
+ fn f64_total_cmp ( left : f64 , right : f64 ) -> Ordering {
68
+ // this is taken from f64::total_cmp on newer rust versions
69
+ let mut left = left. to_bits ( ) as i64 ;
70
+ let mut right = right. to_bits ( ) as i64 ;
71
+ left ^= ( ( ( left >> 63 ) as u64 ) >> 1 ) as i64 ;
72
+ right ^= ( ( ( right >> 63 ) as u64 ) >> 1 ) as i64 ;
73
+ left. cmp ( & right)
74
+ }
75
+
32
76
impl Content {
33
77
pub ( crate ) fn as_key ( & self ) -> Key < ' _ > {
34
78
match * self . resolve_inner ( ) {
0 commit comments