Skip to main content

radiate_utils/datatype/
compare.rs

1use crate::AnyValue;
2use std::cmp::Ordering;
3
4impl<'a> AnyValue<'a> {
5    #[inline]
6    fn variant_rank(&self) -> u8 {
7        match self {
8            AnyValue::Null => 0,
9            AnyValue::Bool(_) => 1,
10
11            AnyValue::UInt8(_) => 2,
12            AnyValue::UInt16(_) => 3,
13            AnyValue::UInt32(_) => 4,
14            AnyValue::UInt64(_) => 5,
15            AnyValue::UInt128(_) => 6,
16
17            AnyValue::Int8(_) => 7,
18            AnyValue::Int16(_) => 8,
19            AnyValue::Int32(_) => 9,
20            AnyValue::Int64(_) => 10,
21            AnyValue::Int128(_) => 11,
22
23            AnyValue::Float32(_) => 12,
24            AnyValue::Float64(_) => 13,
25
26            AnyValue::Usize(_) => 14,
27
28            AnyValue::Duration(_) => 15,
29
30            AnyValue::Char(_) => 16,
31            AnyValue::Str(_) => 17,
32            AnyValue::StrOwned(_) => 18,
33
34            AnyValue::Slice(_) => 19,
35            AnyValue::Vector(_) => 20,
36
37            AnyValue::Dict(_) => 21,
38
39            AnyValue::Struct(_, _) => 22,
40        }
41    }
42
43    fn cmp_same_variant(&self, other: &Self) -> Ordering {
44        use AnyValue::*;
45
46        match (self, other) {
47            (Null, Null) => Ordering::Equal,
48            (Bool(a), Bool(b)) => a.cmp(b),
49
50            (UInt8(a), UInt8(b)) => a.cmp(b),
51            (UInt16(a), UInt16(b)) => a.cmp(b),
52            (UInt32(a), UInt32(b)) => a.cmp(b),
53            (UInt64(a), UInt64(b)) => a.cmp(b),
54            (UInt128(a), UInt128(b)) => a.cmp(b),
55
56            (Int8(a), Int8(b)) => a.cmp(b),
57            (Int16(a), Int16(b)) => a.cmp(b),
58            (Int32(a), Int32(b)) => a.cmp(b),
59            (Int64(a), Int64(b)) => a.cmp(b),
60            (Int128(a), Int128(b)) => a.cmp(b),
61
62            (Float32(a), Float32(b)) => a.total_cmp(b),
63            (Float64(a), Float64(b)) => a.total_cmp(b),
64
65            (Duration(a), Duration(b)) => a.cmp(b),
66
67            (Char(a), Char(b)) => a.cmp(b),
68            (Str(a), Str(b)) => a.cmp(b),
69            (StrOwned(a), StrOwned(b)) => a.cmp(b),
70
71            (Slice(a), Slice(b)) => a.iter().cmp(b.iter()),
72            (Vector(a), Vector(b)) => a.iter().cmp(b.iter()),
73
74            (Dict(a), Dict(b)) => {
75                let mut i = 0;
76                while i < a.len() && i < b.len() {
77                    let (fa, _, va) = &a[i];
78                    let (fb, _, vb) = &b[i];
79
80                    match fa.cmp(fb) {
81                        Ordering::Equal => {}
82                        non_eq => return non_eq,
83                    }
84
85                    match va.cmp(vb) {
86                        Ordering::Equal => {}
87                        non_eq => return non_eq,
88                    }
89
90                    i += 1;
91                }
92
93                a.len().cmp(&b.len())
94            }
95
96            (Struct(fa, va), Struct(fb, vb)) => {
97                match fa.cmp(fb) {
98                    Ordering::Equal => {}
99                    non_eq => return non_eq,
100                }
101
102                let mut i = 0;
103                while i < va.len() && i < vb.len() {
104                    let (name_a, _, va) = &va[i];
105                    let (name_b, _, vb) = &vb[i];
106
107                    match name_a.cmp(name_b) {
108                        Ordering::Equal => {}
109                        non_eq => return non_eq,
110                    }
111
112                    match va.cmp(vb) {
113                        Ordering::Equal => {}
114                        non_eq => return non_eq,
115                    }
116
117                    i += 1;
118                }
119
120                va.len().cmp(&vb.len())
121            }
122
123            _ => unreachable!("cmp_same_variant called with different variants"),
124        }
125    }
126
127    fn fuzzy_cmp(&self, other: &Self) -> Option<Ordering> {
128        use AnyValue::*;
129
130        if self.is_float() && other.is_float() {
131            self.cmp_float(other)
132        } else if self.is_int() && other.is_int() {
133            self.cmp_int(other)
134        } else if self.is_string() && other.is_string() {
135            self.cmp_str(other)
136        } else if self.is_int() && other.is_float() {
137            self.clone()
138                .cast(&other.dtype())
139                .and_then(|v| v.fuzzy_cmp(other))
140        } else if self.is_float() && other.is_int() {
141            self.clone()
142                .cast(&other.dtype())
143                .and_then(|v| v.fuzzy_cmp(other))
144        } else {
145            let res = match (self, other) {
146                (Null, Null) => Ordering::Equal,
147                (Bool(a), Bool(b)) => a.cmp(b),
148
149                (Vector(a), Vector(b)) => a.iter().cmp(b.iter()),
150                (Slice(a), Slice(b)) => a.iter().cmp(b.iter()),
151
152                _ => return None,
153            };
154
155            Some(res)
156        }
157    }
158
159    fn cmp_float(&self, other: &Self) -> Option<Ordering> {
160        use AnyValue::*;
161
162        match (self, other) {
163            (Float32(a), Float32(b)) => Some(a.total_cmp(b)),
164            (Float64(a), Float64(b)) => Some(a.total_cmp(b)),
165            (Float32(a), Float64(b)) => Some((*a as f64).total_cmp(b)),
166            (Float64(a), Float32(b)) => Some(a.total_cmp(&(*b as f64))),
167            _ => None,
168        }
169    }
170
171    fn cmp_str(&self, other: &Self) -> Option<Ordering> {
172        use AnyValue::*;
173
174        match (self, other) {
175            (Str(a), Str(b)) => Some(a.cmp(b)),
176            (StrOwned(a), StrOwned(b)) => Some(a.cmp(b)),
177            (Char(a), Char(b)) => Some(a.cmp(b)),
178
179            (Str(a), StrOwned(b)) => Some(a.cmp(&b.as_str())),
180            (StrOwned(a), Str(b)) => Some(a.as_str().cmp(b)),
181            _ => None,
182        }
183    }
184
185    fn cmp_int(&self, other: &Self) -> Option<Ordering> {
186        use AnyValue::*;
187
188        match (self, other) {
189            (Int8(a), Int8(b)) => Some(a.cmp(b)),
190            (Int16(a), Int16(b)) => Some(a.cmp(b)),
191            (Int32(a), Int32(b)) => Some(a.cmp(b)),
192            (Int64(a), Int64(b)) => Some(a.cmp(b)),
193            (Int128(a), Int128(b)) => Some(a.cmp(b)),
194
195            (UInt8(a), UInt8(b)) => Some(a.cmp(b)),
196            (UInt16(a), UInt16(b)) => Some(a.cmp(b)),
197            (UInt32(a), UInt32(b)) => Some(a.cmp(b)),
198            (UInt64(a), UInt64(b)) => Some(a.cmp(b)),
199            (UInt128(a), UInt128(b)) => Some(a.cmp(b)),
200
201            (Int8(a), Int16(b)) => Some((*a as i16).cmp(b)),
202            (Int8(a), Int32(b)) => Some((*a as i32).cmp(b)),
203            (Int8(a), Int64(b)) => Some((*a as i64).cmp(b)),
204            (Int8(a), Int128(b)) => Some((*a as i128).cmp(b)),
205            (Int8(a), UInt8(b)) => Some((*a as i16).cmp(&(*b as i16))),
206            (Int8(a), UInt16(b)) => Some((*a as i32).cmp(&(*b as i32))),
207            (Int8(a), UInt32(b)) => Some((*a as i64).cmp(&(*b as i64))),
208            (Int8(a), UInt64(b)) => Some((*a as i128).cmp(&(*b as i128))),
209
210            (Int16(a), Int8(b)) => Some(a.cmp(&(*b as i16))),
211            (Int16(a), Int32(b)) => Some((*a as i32).cmp(b)),
212            (Int16(a), Int64(b)) => Some((*a as i64).cmp(b)),
213            (Int16(a), Int128(b)) => Some((*a as i128).cmp(b)),
214            (Int16(a), UInt8(b)) => Some((*a as i32).cmp(&(*b as i32))),
215            (Int16(a), UInt16(b)) => Some((*a as i32).cmp(&(*b as i32))),
216            (Int16(a), UInt32(b)) => Some((*a as i64).cmp(&(*b as i64))),
217            (Int16(a), UInt64(b)) => Some((*a as i128).cmp(&(*b as i128))),
218
219            (Int32(a), Int8(b)) => Some(a.cmp(&(*b as i32))),
220            (Int32(a), Int16(b)) => Some(a.cmp(&(*b as i32))),
221            (Int32(a), Int64(b)) => Some((*a as i64).cmp(b)),
222            (Int32(a), Int128(b)) => Some((*a as i128).cmp(b)),
223            (Int32(a), UInt8(b)) => Some((*a as i64).cmp(&(*b as i64))),
224            (Int32(a), UInt16(b)) => Some((*a as i64).cmp(&(*b as i64))),
225            (Int32(a), UInt32(b)) => Some((*a as i64).cmp(&(*b as i64))),
226            (Int32(a), UInt64(b)) => Some((*a as i128).cmp(&(*b as i128))),
227
228            (Int64(a), Int8(b)) => Some(a.cmp(&(*b as i64))),
229            (Int64(a), Int16(b)) => Some(a.cmp(&(*b as i64))),
230            (Int64(a), Int32(b)) => Some(a.cmp(&(*b as i64))),
231            (Int64(a), Int128(b)) => Some((*a as i128).cmp(b)),
232            (Int64(a), UInt8(b)) => Some((*a as i128).cmp(&(*b as i128))),
233            (Int64(a), UInt16(b)) => Some((*a as i128).cmp(&(*b as i128))),
234            (Int64(a), UInt32(b)) => Some((*a as i128).cmp(&(*b as i128))),
235            (Int64(a), UInt64(b)) => Some((*a as i128).cmp(&(*b as i128))),
236
237            (UInt8(a), UInt16(b)) => Some((*a as u16).cmp(b)),
238            (UInt8(a), UInt32(b)) => Some((*a as u32).cmp(b)),
239            (UInt8(a), UInt64(b)) => Some((*a as u64).cmp(b)),
240            (UInt8(a), UInt128(b)) => Some((*a as u128).cmp(b)),
241            (UInt8(a), Int8(b)) => Some((*a as i16).cmp(&(*b as i16))),
242            (UInt8(a), Int16(b)) => Some((*a as i32).cmp(&(*b as i32))),
243            (UInt8(a), Int32(b)) => Some((*a as i64).cmp(&(*b as i64))),
244            (UInt8(a), Int64(b)) => Some((*a as i128).cmp(&(*b as i128))),
245
246            (UInt16(a), UInt8(b)) => Some(a.cmp(&(*b as u16))),
247            (UInt16(a), UInt32(b)) => Some((*a as u32).cmp(b)),
248            (UInt16(a), UInt64(b)) => Some((*a as u64).cmp(b)),
249            (UInt16(a), UInt128(b)) => Some((*a as u128).cmp(b)),
250            (UInt16(a), Int8(b)) => Some((*a as i32).cmp(&(*b as i32))),
251            (UInt16(a), Int16(b)) => Some((*a as i32).cmp(&(*b as i32))),
252            (UInt16(a), Int32(b)) => Some((*a as i64).cmp(&(*b as i64))),
253            (UInt16(a), Int64(b)) => Some((*a as i128).cmp(&(*b as i128))),
254
255            (UInt32(a), UInt8(b)) => Some(a.cmp(&(*b as u32))),
256            (UInt32(a), UInt16(b)) => Some(a.cmp(&(*b as u32))),
257            (UInt32(a), UInt64(b)) => Some((*a as u64).cmp(b)),
258            (UInt32(a), UInt128(b)) => Some((*a as u128).cmp(b)),
259            (UInt32(a), Int8(b)) => Some((*a as i64).cmp(&(*b as i64))),
260            (UInt32(a), Int16(b)) => Some((*a as i64).cmp(&(*b as i64))),
261            (UInt32(a), Int32(b)) => Some((*a as i64).cmp(&(*b as i64))),
262            (UInt32(a), Int64(b)) => Some((*a as i128).cmp(&(*b as i128))),
263
264            (UInt64(a), UInt8(b)) => Some(a.cmp(&(*b as u64))),
265            (UInt64(a), UInt16(b)) => Some(a.cmp(&(*b as u64))),
266            (UInt64(a), UInt32(b)) => Some(a.cmp(&(*b as u64))),
267            (UInt64(a), UInt128(b)) => Some((*a as u128).cmp(b)),
268            (UInt64(a), Int8(b)) => Some((*a as i128).cmp(&(*b as i128))),
269            (UInt64(a), Int16(b)) => Some((*a as i128).cmp(&(*b as i128))),
270            (UInt64(a), Int32(b)) => Some((*a as i128).cmp(&(*b as i128))),
271            (UInt64(a), Int64(b)) => Some((*a as i128).cmp(&(*b as i128))),
272            _ => None,
273        }
274    }
275}
276
277impl<'a> PartialOrd for AnyValue<'a> {
278    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
279        Some(self.cmp(other))
280    }
281}
282
283impl<'a> Ord for AnyValue<'a> {
284    fn cmp(&self, other: &Self) -> Ordering {
285        if let Some(like_cmp) = self.fuzzy_cmp(other) {
286            like_cmp
287        } else {
288            match self.variant_rank().cmp(&other.variant_rank()) {
289                Ordering::Equal => self.cmp_same_variant(other),
290                non_eq => non_eq,
291            }
292        }
293    }
294}