1use std::{cmp::Ordering, collections::HashMap, hash::BuildHasher};
2
3pub trait AmadeusOrd {
4 fn amadeus_cmp(&self, other: &Self) -> Ordering;
5}
6
7macro_rules! ord {
8 ($($t:ty)*) => {$(
9 impl AmadeusOrd for $t {
10 fn amadeus_cmp(&self, other: &Self) -> Ordering {
11 Ord::cmp(self, other)
12 }
13 }
14 )*}
15}
16ord!(bool u8 i8 u16 i16 u32 i32 u64 i64 String);
17
18impl AmadeusOrd for f32 {
19 fn amadeus_cmp(&self, other: &Self) -> Ordering {
20 Ord::cmp(
21 &ordered_float::OrderedFloat(*self),
22 &ordered_float::OrderedFloat(*other),
23 )
24 }
25}
26impl AmadeusOrd for f64 {
27 fn amadeus_cmp(&self, other: &Self) -> Ordering {
28 Ord::cmp(
29 &ordered_float::OrderedFloat(*self),
30 &ordered_float::OrderedFloat(*other),
31 )
32 }
33}
34
35impl<T> AmadeusOrd for &T
36where
37 T: AmadeusOrd + ?Sized,
38{
39 fn amadeus_cmp(&self, other: &Self) -> Ordering {
40 (**self).amadeus_cmp(&**other)
41 }
42}
43
44impl<T> AmadeusOrd for Box<T>
45where
46 T: AmadeusOrd,
47{
48 fn amadeus_cmp(&self, other: &Self) -> Ordering {
49 (**self).amadeus_cmp(&**other)
50 }
51}
52
53impl<T> AmadeusOrd for Option<T>
55where
56 T: AmadeusOrd,
57{
58 fn amadeus_cmp(&self, other: &Self) -> Ordering {
59 match (self, other) {
60 (Some(a), Some(b)) => a.amadeus_cmp(b),
61 (None, None) => Ordering::Equal,
62 (None, Some(_)) => Ordering::Greater,
63 (Some(_), None) => Ordering::Less,
64 }
65 }
66}
67
68impl<T> AmadeusOrd for Vec<T>
69where
70 T: AmadeusOrd,
71{
72 fn amadeus_cmp(&self, other: &Self) -> Ordering {
73 for i in 0..self.len().min(other.len()) {
74 match self[i].amadeus_cmp(&other[i]) {
75 Ordering::Equal => (),
76 res => return res,
77 }
78 }
79 self.len().cmp(&other.len())
80 }
81}
82
83impl<K, V, S> AmadeusOrd for HashMap<K, V, S>
84where
85 K: AmadeusOrd,
86 V: AmadeusOrd,
87 S: BuildHasher,
88{
89 fn amadeus_cmp(&self, other: &Self) -> Ordering {
90 let mut keys: Vec<(&K, &V, bool)> = self
91 .iter()
92 .map(|(k, v)| (k, v, false))
93 .chain(other.iter().map(|(k, v)| (k, v, true)))
94 .collect();
95 keys.sort_by(|(a, _, _), (b, _, _)| a.amadeus_cmp(b));
96 let mut keys = &*keys;
97 while keys.len() >= 2 {
98 let ((a_k, a_v, a_r), (b_k, b_v, b_r)) = (keys[0], keys[1]);
99 if !a_r && b_r {
100 match a_k.amadeus_cmp(b_k) {
101 Ordering::Equal => (),
102 res => return res,
103 }
104 match a_v.amadeus_cmp(b_v) {
105 Ordering::Equal => (),
106 res => return res,
107 }
108 keys = &keys[2..];
109 } else if !a_r {
110 return Ordering::Greater;
111 } else {
112 return Ordering::Less;
113 }
114 }
115 if keys.len() == 1 {
116 if !keys[0].2 {
117 Ordering::Greater
118 } else {
119 Ordering::Less
120 }
121 } else {
122 Ordering::Equal
123 }
124 }
125}
126
127macro_rules! ord {
128 ($($i:tt)*) => {$(
129 impl<T> AmadeusOrd for [T; $i]
130 where
131 T: AmadeusOrd
132 {
133 fn amadeus_cmp(&self, other: &Self) -> Ordering {
134 for (a,b) in self.iter().zip(other.iter()) {
135 match a.amadeus_cmp(b) {
136 Ordering::Equal => (),
137 res => return res,
138 }
139 }
140 Ordering::Equal
141 }
142 }
143 )*};
144}
145array!(ord);
146
147macro_rules! ord {
148 ($len:tt $($t:ident $i:tt)*) => {
149 impl<$($t,)*> AmadeusOrd for ($($t,)*) where $($t: AmadeusOrd,)* {
150 #[allow(unused_variables)]
151 fn amadeus_cmp(&self, other: &Self) -> Ordering {
152 Ordering::Equal
153 $(.then_with(|| self.$i.amadeus_cmp(&other.$i)))*
154 }
155 }
156 };
157}
158tuple!(ord);