valitron/value/
cmp.rs

1use std::cmp::Ordering;
2
3use super::{
4    float::{Float32, Float64},
5    Value,
6};
7
8macro_rules! primitive_eq {
9    ($($val:ident($ty:ty)),+) => {
10        $(
11            impl PartialEq<Value> for $ty {
12                fn eq(&self, other: &Value) -> bool {
13                    if let Value::$val(n) = other {
14                        self == n
15                    } else {
16                        unreachable!("type mismatch")
17                    }
18                }
19            }
20            impl PartialEq<$ty> for Value {
21                fn eq(&self, other: &$ty) -> bool {
22                    if let Value::$val(n) = self {
23                        n == other
24                    } else {
25                        unreachable!("type mismatch")
26                    }
27                }
28            }
29
30            impl PartialEq<&Value> for $ty {
31                fn eq(&self, other: &&Value) -> bool {
32                    if let Value::$val(n) = other {
33                        self == n
34                    } else {
35                        unreachable!("type mismatch")
36                    }
37                }
38            }
39            impl PartialEq<$ty> for &Value {
40                fn eq(&self, other: &$ty) -> bool {
41                    if let Value::$val(n) = self {
42                        n == other
43                    } else {
44                        unreachable!("type mismatch")
45                    }
46                }
47            }
48
49            impl PartialEq<&mut Value> for $ty {
50                fn eq(&self, other: &&mut Value) -> bool {
51                    if let Value::$val(n) = other {
52                        self == n
53                    } else {
54                        unreachable!("type mismatch")
55                    }
56                }
57            }
58            impl PartialEq<$ty> for &mut Value {
59                fn eq(&self, other: &$ty) -> bool {
60                    if let Value::$val(n) = self {
61                        n == other
62                    } else {
63                        unreachable!("type mismatch")
64                    }
65                }
66            }
67        )+
68    };
69}
70
71macro_rules! primitive_ord {
72    ($($val:ident($ty:ty)),+) => {
73        $(
74            impl PartialOrd<Value> for $ty {
75                fn partial_cmp(&self, other: &Value) -> Option<Ordering> {
76                    if let Value::$val(n) = other {
77                        self.partial_cmp(n)
78                    } else {
79                        None
80                    }
81                }
82            }
83            impl PartialOrd<$ty> for Value {
84                fn partial_cmp(&self, other: &$ty) -> Option<Ordering> {
85                    if let Value::$val(n) = self {
86                        n.partial_cmp(other)
87                    } else {
88                        None
89                    }
90                }
91            }
92
93            impl PartialOrd<&Value> for $ty {
94                fn partial_cmp(&self, other: &&Value) -> Option<Ordering> {
95                    if let Value::$val(n) = other {
96                        self.partial_cmp(n)
97                    } else {
98                        None
99                    }
100                }
101            }
102            impl PartialOrd<$ty> for &Value {
103                fn partial_cmp(&self, other: &$ty) -> Option<Ordering> {
104                    if let Value::$val(n) = self {
105                        n.partial_cmp(other)
106                    } else {
107                        None
108                    }
109                }
110            }
111
112            impl PartialOrd<&mut Value> for $ty {
113                fn partial_cmp(&self, other: &&mut Value) -> Option<Ordering> {
114                    if let Value::$val(n) = other {
115                        self.partial_cmp(n)
116                    } else {
117                        None
118                    }
119                }
120            }
121            impl PartialOrd<$ty> for &mut Value {
122                fn partial_cmp(&self, other: &$ty) -> Option<Ordering> {
123                    if let Value::$val(n) = self {
124                        n.partial_cmp(other)
125                    } else {
126                        None
127                    }
128                }
129            }
130        )+
131    };
132}
133
134primitive_eq!(
135    Uint8(u8),
136    Int8(i8),
137    Uint16(u16),
138    Int16(i16),
139    Uint32(u32),
140    Int32(i32),
141    Uint64(u64),
142    Int64(i64),
143    String(String),
144    Boolean(bool),
145    Char(char)
146);
147
148primitive_ord!(
149    Uint8(u8),
150    Int8(i8),
151    Uint16(u16),
152    Int16(i16),
153    Uint32(u32),
154    Int32(i32),
155    Uint64(u64),
156    Int64(i64),
157    String(String),
158    Boolean(bool),
159    Char(char)
160);
161
162impl PartialEq<Value> for f32 {
163    fn eq(&self, other: &Value) -> bool {
164        if let Value::Float32(Float32(f)) = other {
165            if self.is_finite() && f.is_finite() {
166                self == f
167            } else {
168                false
169            }
170        } else {
171            unreachable!("type mismatch")
172        }
173    }
174}
175
176impl PartialEq<f32> for Value {
177    fn eq(&self, other: &f32) -> bool {
178        if let Value::Float32(Float32(f)) = self {
179            if f.is_finite() && other.is_finite() {
180                f == other
181            } else {
182                false
183            }
184        } else {
185            unreachable!("type mismatch")
186        }
187    }
188}
189
190impl PartialEq<&Value> for f32 {
191    fn eq(&self, other: &&Value) -> bool {
192        if let Value::Float32(Float32(f)) = other {
193            if self.is_finite() && f.is_finite() {
194                self == f
195            } else {
196                false
197            }
198        } else {
199            unreachable!("type mismatch")
200        }
201    }
202}
203
204impl PartialEq<f32> for &Value {
205    fn eq(&self, other: &f32) -> bool {
206        if let Value::Float32(Float32(f)) = self {
207            if f.is_finite() && other.is_finite() {
208                f == other
209            } else {
210                false
211            }
212        } else {
213            unreachable!("type mismatch")
214        }
215    }
216}
217impl PartialEq<&mut Value> for f32 {
218    fn eq(&self, other: &&mut Value) -> bool {
219        if let Value::Float32(Float32(f)) = other {
220            if self.is_finite() && f.is_finite() {
221                self == f
222            } else {
223                false
224            }
225        } else {
226            unreachable!("type mismatch")
227        }
228    }
229}
230
231impl PartialEq<f32> for &mut Value {
232    fn eq(&self, other: &f32) -> bool {
233        if let Value::Float32(Float32(f)) = self {
234            if f.is_finite() && other.is_finite() {
235                f == other
236            } else {
237                false
238            }
239        } else {
240            unreachable!("type mismatch")
241        }
242    }
243}
244
245impl PartialEq<Value> for f64 {
246    fn eq(&self, other: &Value) -> bool {
247        if let Value::Float64(Float64(f)) = other {
248            if self.is_finite() && f.is_finite() {
249                self == f
250            } else {
251                false
252            }
253        } else {
254            unreachable!("type mismatch")
255        }
256    }
257}
258
259impl PartialEq<f64> for Value {
260    fn eq(&self, other: &f64) -> bool {
261        if let Value::Float64(Float64(f)) = self {
262            if f.is_finite() && other.is_finite() {
263                f == other
264            } else {
265                false
266            }
267        } else {
268            unreachable!("type mismatch")
269        }
270    }
271}
272
273impl PartialEq<&Value> for f64 {
274    fn eq(&self, other: &&Value) -> bool {
275        if let Value::Float64(Float64(f)) = other {
276            if self.is_finite() && f.is_finite() {
277                self == f
278            } else {
279                false
280            }
281        } else {
282            unreachable!("type mismatch")
283        }
284    }
285}
286
287impl PartialEq<f64> for &Value {
288    fn eq(&self, other: &f64) -> bool {
289        if let Value::Float64(Float64(f)) = self {
290            if f.is_finite() && other.is_finite() {
291                f == other
292            } else {
293                false
294            }
295        } else {
296            unreachable!("type mismatch")
297        }
298    }
299}
300
301impl PartialEq<&mut Value> for f64 {
302    fn eq(&self, other: &&mut Value) -> bool {
303        if let Value::Float64(Float64(f)) = other {
304            if self.is_finite() && f.is_finite() {
305                self == f
306            } else {
307                false
308            }
309        } else {
310            unreachable!("type mismatch")
311        }
312    }
313}
314
315impl PartialEq<f64> for &mut Value {
316    fn eq(&self, other: &f64) -> bool {
317        if let Value::Float64(Float64(f)) = self {
318            if f.is_finite() && other.is_finite() {
319                f == other
320            } else {
321                false
322            }
323        } else {
324            unreachable!("type mismatch")
325        }
326    }
327}
328
329#[test]
330fn all() {
331    let mut value = Value::Uint8(10);
332
333    assert!(value == 10_u8);
334    assert!(value > 9_u8);
335    assert!(&value == 10_u8);
336    assert!(&value > 9_u8);
337    assert!(&mut value == 10_u8);
338    assert!(&mut value > 9_u8);
339
340    let value = Value::Float32(Float32(1.1));
341    let f = 1.1_f32;
342    assert!(value == f);
343
344    let value_nan = Value::Float32(Float32(f32::NAN));
345    let f_nan = f32::NAN;
346    assert!(value_nan != f_nan);
347}
348
349#[test]
350#[should_panic]
351fn type_mismatch() {
352    let value = Value::Uint8(10);
353    assert!(value == 10_i8);
354}