drasi_core/evaluation/variable_value/
partial_eq.rs

1// Copyright 2024 The Drasi Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use super::VariableValue;
16use crate::evaluation::variable_value::duration::Duration;
17use crate::evaluation::variable_value::float::Float;
18use chrono::{NaiveDate, NaiveTime};
19
20fn eq_i64(value: &VariableValue, other: i64) -> bool {
21    match value {
22        VariableValue::Integer(n) => n.as_i64() == Some(other),
23        VariableValue::Float(n) => n.as_f64() == Some(other as f64),
24        _ => false,
25    }
26}
27
28fn eq_u64(value: &VariableValue, other: u64) -> bool {
29    match value {
30        VariableValue::Integer(n) => n.as_u64() == Some(other),
31        VariableValue::Float(n) => n.as_f64() == Some(other as f64),
32        _ => false,
33    }
34}
35
36fn eq_f32(value: &VariableValue, other: f32) -> bool {
37    match value {
38        VariableValue::Float(n) => n.as_f32() == Some(other),
39        VariableValue::Integer(n) => n.as_i64().is_some_and(|n| n as f64 == other as f64),
40        _ => false,
41    }
42}
43
44fn eq_f64(value: &VariableValue, other: f64) -> bool {
45    match value {
46        VariableValue::Float(n) => n.as_f64() == Some(other),
47        VariableValue::Integer(n) => n.as_i64().is_some_and(|n| n as f64 == other),
48        _ => false,
49    }
50}
51
52fn eq_bool(value: &VariableValue, other: bool) -> bool {
53    value.as_bool() == Some(other)
54}
55
56fn eq_str(value: &VariableValue, other: &str) -> bool {
57    value.as_str() == Some(other)
58}
59
60impl PartialEq<str> for VariableValue {
61    fn eq(&self, other: &str) -> bool {
62        eq_str(self, other)
63    }
64}
65
66impl PartialEq<&str> for VariableValue {
67    fn eq(&self, other: &&str) -> bool {
68        eq_str(self, other)
69    }
70}
71
72impl PartialEq<VariableValue> for str {
73    fn eq(&self, other: &VariableValue) -> bool {
74        eq_str(other, self)
75    }
76}
77
78impl PartialEq<VariableValue> for &str {
79    fn eq(&self, other: &VariableValue) -> bool {
80        eq_str(other, self)
81    }
82}
83
84impl PartialEq<String> for VariableValue {
85    fn eq(&self, other: &String) -> bool {
86        eq_str(self, other.as_str())
87    }
88}
89
90impl PartialEq<VariableValue> for String {
91    fn eq(&self, other: &VariableValue) -> bool {
92        eq_str(other, self.as_str())
93    }
94}
95
96impl PartialEq<Float> for VariableValue {
97    fn eq(&self, other: &Float) -> bool {
98        eq_f64(
99            self,
100            match other.as_f64() {
101                Some(n) => n,
102                None => unreachable!(),
103            },
104        )
105    }
106}
107
108impl PartialEq<NaiveTime> for VariableValue {
109    fn eq(&self, other: &NaiveTime) -> bool {
110        match self {
111            VariableValue::LocalTime(time) => time == other,
112            _ => false,
113        }
114    }
115}
116
117impl PartialEq<Duration> for VariableValue {
118    fn eq(&self, other: &Duration) -> bool {
119        match self {
120            VariableValue::Duration(duration) => duration == other,
121            _ => false,
122        }
123    }
124}
125
126impl PartialEq<NaiveDate> for VariableValue {
127    fn eq(&self, other: &NaiveDate) -> bool {
128        match self {
129            VariableValue::Date(date) => date == other,
130            _ => false,
131        }
132    }
133}
134
135impl PartialEq<VariableValue> for VariableValue {
136    fn eq(&self, other: &VariableValue) -> bool {
137        match (self, other) {
138            (VariableValue::Integer(n), VariableValue::Integer(m)) => n == m,
139            (VariableValue::Float(n), VariableValue::Float(m)) => n == m,
140            (VariableValue::Integer(n), VariableValue::Float(m)) => n.as_i64().is_some_and(|n| {
141                n as f64
142                    == match m.as_f64() {
143                        Some(m) => m,
144                        None => unreachable!(),
145                    }
146            }),
147            (VariableValue::Float(n), VariableValue::Integer(m)) => m.as_i64().is_some_and(|m| {
148                m as f64
149                    == match n.as_f64() {
150                        Some(n) => n,
151                        None => unreachable!(),
152                    }
153            }),
154            (VariableValue::Bool(n), VariableValue::Bool(m)) => n == m,
155            (VariableValue::String(n), VariableValue::String(m)) => n == m,
156            (VariableValue::List(list1), VariableValue::List(list2)) => list1 == list2,
157            (VariableValue::Null, VariableValue::Null) => true,
158            (VariableValue::Object(obj1), VariableValue::Object(obj2)) => obj1 == obj2,
159            (VariableValue::Date(date1), VariableValue::Date(date2)) => date1 == date2,
160            (VariableValue::LocalTime(time1), VariableValue::LocalTime(time2)) => time1 == time2,
161            (VariableValue::ZonedTime(time1), VariableValue::ZonedTime(time2)) => time1 == time2,
162            (VariableValue::LocalDateTime(time1), VariableValue::LocalDateTime(time2)) => {
163                time1 == time2
164            }
165            (VariableValue::ZonedDateTime(time1), VariableValue::ZonedDateTime(time2)) => {
166                time1 == time2
167            }
168            (VariableValue::Duration(duration1), VariableValue::Duration(duration2)) => {
169                duration1 == duration2
170            }
171            (VariableValue::Element(element1), VariableValue::Element(element2)) => {
172                element1 == element2
173            }
174            (
175                VariableValue::ElementReference(reference1),
176                VariableValue::ElementReference(reference2),
177            ) => reference1 == reference2,
178            (
179                VariableValue::ElementMetadata(metadata1),
180                VariableValue::ElementMetadata(metadata2),
181            ) => metadata1 == metadata2,
182            (VariableValue::Expression(e1), VariableValue::Expression(e2)) => e1 == e2,
183            (VariableValue::ListRange(r1), VariableValue::ListRange(r2)) => r1 == r2,
184            (VariableValue::Awaiting, VariableValue::Awaiting) => true,
185            _ => false,
186        }
187    }
188}
189
190macro_rules! partialeq_numeric {
191    ($($eq:ident [$($ty:ty)*])*) => {
192        $($(
193            impl PartialEq<$ty> for VariableValue {
194                fn eq(&self, other: &$ty) -> bool {
195                    $eq(self, *other as _)
196                }
197            }
198
199            impl PartialEq<VariableValue> for $ty {
200                fn eq(&self, other: &VariableValue) -> bool {
201                    $eq(other, *self as _)
202                }
203            }
204
205            impl<'a> PartialEq<$ty> for &'a VariableValue {
206                fn eq(&self, other: &$ty) -> bool {
207                    $eq(*self, *other as _)
208                }
209            }
210
211            impl<'a> PartialEq<$ty> for &'a mut VariableValue {
212                fn eq(&self, other: &$ty) -> bool {
213                    $eq(*self, *other as _)
214                }
215            }
216        )*)*
217    }
218}
219
220partialeq_numeric! {
221    eq_i64[i8 i16 i32 i64 isize]
222    eq_u64[u8 u16 u32 u64 usize]
223    eq_f32[f32]
224    eq_f64[f64]
225    eq_bool[bool]
226}
227
228use std::cmp::Ordering;
229impl PartialOrd for VariableValue {
230    fn partial_cmp(&self, other: &VariableValue) -> Option<Ordering> {
231        match (self, other) {
232            (VariableValue::Integer(lhs), VariableValue::Integer(rhs)) => {
233                lhs.as_i64().partial_cmp(&rhs.as_i64())
234            }
235            (VariableValue::Float(lhs), VariableValue::Float(rhs)) => {
236                lhs.as_f64().partial_cmp(&rhs.as_f64())
237            }
238            (VariableValue::Integer(lhs), VariableValue::Float(rhs)) => lhs
239                .as_i64()
240                .map(|lhs| lhs as f64)
241                .partial_cmp(&rhs.as_f64()),
242            (VariableValue::Float(lhs), VariableValue::Integer(rhs)) => lhs
243                .as_f64()
244                .partial_cmp(&rhs.as_i64().map(|rhs| rhs as f64)),
245            (
246                VariableValue::Integer(_),
247                VariableValue::String(_)
248                | VariableValue::Null
249                | VariableValue::Bool(_)
250                | VariableValue::Date(_)
251                | VariableValue::LocalTime(_)
252                | VariableValue::LocalDateTime(_)
253                | VariableValue::ZonedTime(_)
254                | VariableValue::ZonedDateTime(_)
255                | VariableValue::Duration(_),
256            ) => Some(Ordering::Greater),
257            (
258                VariableValue::Float(_),
259                VariableValue::String(_)
260                | VariableValue::Null
261                | VariableValue::Bool(_)
262                | VariableValue::Date(_)
263                | VariableValue::LocalTime(_)
264                | VariableValue::LocalDateTime(_)
265                | VariableValue::ZonedTime(_)
266                | VariableValue::ZonedDateTime(_)
267                | VariableValue::Duration(_),
268            ) => Some(Ordering::Greater),
269            (VariableValue::String(s1), VariableValue::String(s2)) => s1.partial_cmp(s2),
270            (
271                VariableValue::String(_),
272                VariableValue::Null
273                | VariableValue::Bool(_)
274                | VariableValue::Date(_)
275                | VariableValue::LocalTime(_)
276                | VariableValue::LocalDateTime(_)
277                | VariableValue::ZonedTime(_)
278                | VariableValue::ZonedDateTime(_)
279                | VariableValue::Duration(_),
280            ) => Some(Ordering::Greater),
281            (VariableValue::String(_), VariableValue::Integer(_) | VariableValue::Float(_)) => {
282                Some(Ordering::Less)
283            }
284            (VariableValue::Null, VariableValue::Null) => Some(Ordering::Equal),
285            (
286                VariableValue::Null,
287                VariableValue::Bool(_)
288                | VariableValue::Float(_)
289                | VariableValue::Integer(_)
290                | VariableValue::Date(_)
291                | VariableValue::LocalTime(_)
292                | VariableValue::LocalDateTime(_)
293                | VariableValue::ZonedTime(_)
294                | VariableValue::ZonedDateTime(_)
295                | VariableValue::Duration(_),
296            ) => Some(Ordering::Less),
297            (VariableValue::Bool(b1), VariableValue::Bool(b2)) => b1.partial_cmp(b2),
298            (
299                VariableValue::Bool(_),
300                VariableValue::String(_)
301                | VariableValue::Date(_)
302                | VariableValue::Float(_)
303                | VariableValue::Integer(_)
304                | VariableValue::LocalTime(_)
305                | VariableValue::LocalDateTime(_)
306                | VariableValue::ZonedTime(_)
307                | VariableValue::ZonedDateTime(_)
308                | VariableValue::Duration(_),
309            ) => Some(Ordering::Less),
310            (VariableValue::Date(d1), VariableValue::Date(d2)) => d1.partial_cmp(d2),
311            (
312                VariableValue::Date(_),
313                VariableValue::LocalTime(_)
314                | VariableValue::String(_)
315                | VariableValue::Float(_)
316                | VariableValue::Integer(_)
317                | VariableValue::LocalDateTime(_)
318                | VariableValue::ZonedTime(_)
319                | VariableValue::ZonedDateTime(_)
320                | VariableValue::Duration(_),
321            ) => Some(Ordering::Less),
322            (VariableValue::LocalTime(t1), VariableValue::LocalTime(t2)) => t1.partial_cmp(t2),
323            (
324                VariableValue::LocalTime(_),
325                VariableValue::LocalDateTime(_)
326                | VariableValue::Float(_)
327                | VariableValue::String(_)
328                | VariableValue::Integer(_)
329                | VariableValue::ZonedTime(_)
330                | VariableValue::ZonedDateTime(_)
331                | VariableValue::Duration(_),
332            ) => Some(Ordering::Less),
333            (VariableValue::LocalDateTime(t1), VariableValue::LocalDateTime(t2)) => {
334                t1.partial_cmp(t2)
335            }
336            (
337                VariableValue::LocalDateTime(_),
338                VariableValue::ZonedTime(_)
339                | VariableValue::Float(_)
340                | VariableValue::String(_)
341                | VariableValue::Integer(_)
342                | VariableValue::ZonedDateTime(_)
343                | VariableValue::Duration(_),
344            ) => Some(Ordering::Less),
345            (VariableValue::ZonedTime(t1), VariableValue::ZonedTime(t2)) => {
346                t1.time().partial_cmp(t2.time())
347            }
348            (
349                VariableValue::ZonedTime(_),
350                VariableValue::ZonedDateTime(_)
351                | VariableValue::Float(_)
352                | VariableValue::Integer(_)
353                | VariableValue::String(_)
354                | VariableValue::Duration(_),
355            ) => Some(Ordering::Less),
356            (VariableValue::ZonedDateTime(t1), VariableValue::ZonedDateTime(t2)) => {
357                t1.datetime().partial_cmp(t2.datetime())
358            }
359            (
360                VariableValue::ZonedDateTime(_),
361                VariableValue::Float(_)
362                | VariableValue::String(_)
363                | VariableValue::Integer(_)
364                | VariableValue::Duration(_),
365            ) => Some(Ordering::Less),
366            (VariableValue::Duration(d1), VariableValue::Duration(d2)) => {
367                d1.duration().partial_cmp(d2.duration())
368            }
369            (
370                VariableValue::Duration(_),
371                VariableValue::Float(_) | VariableValue::String(_) | VariableValue::Integer(_),
372            ) => Some(Ordering::Less),
373            _ => None,
374        }
375    }
376}
377
378// impl Ord for VariableValue {
379//     fn cmp(&self, other: &Self) -> Ordering {
380//         Ordering::Equal
381//     }
382// }