1use crate::{util, Bag, List, Tuple};
2use crate::{Value, Variant};
3
4pub trait Comparable {
5 fn is_comparable_to(&self, rhs: &Self) -> bool;
6}
7
8impl Comparable for Value {
9 fn is_comparable_to(&self, rhs: &Self) -> bool {
11 match (self, rhs) {
12 (Value::Missing | Value::Null, _)
14 | (_, Value::Missing | Value::Null)
15 | (Value::Boolean(_), Value::Boolean(_))
17 | (Value::String(_), Value::String(_))
18 | (Value::Blob(_), Value::Blob(_))
19 | (Value::DateTime(_), Value::DateTime(_))
20 | (Value::List(_), Value::List(_))
21 | (Value::Bag(_), Value::Bag(_))
22 | (Value::Tuple(_), Value::Tuple(_))
23 | (
25 Value::Integer(_) | Value::Real(_) | Value::Decimal(_),
26 Value::Integer(_) | Value::Real(_) | Value::Decimal(_),
27 )=> true,
28 (Value::Variant(lhs), Value::Variant(rhs)) => {
29 lhs.is_comparable_to(rhs)
30 }
31 (_, _) => false,
32 }
33 }
34}
35
36pub trait NullableEq {
38 fn eq(&self, rhs: &Self) -> Value;
39
40 fn neq(&self, rhs: &Self) -> Value {
41 let eq_result = NullableEq::eq(self, rhs);
42 match eq_result {
43 Value::Boolean(_) | Value::Null => !eq_result,
44 _ => Value::Missing,
45 }
46 }
47
48 fn eqg(&self, rhs: &Self) -> Value;
53
54 fn neqg(&self, rhs: &Self) -> Value {
55 let eqg_result = NullableEq::eqg(self, rhs);
56 match eqg_result {
57 Value::Boolean(_) | Value::Null => !eqg_result,
58 _ => Value::Missing,
59 }
60 }
61}
62
63#[derive(Eq, PartialEq, Debug)]
65pub struct EqualityValue<'a, const NULLS_EQUAL: bool, const NAN_EQUAL: bool, T>(pub &'a T);
66
67impl<const GROUP_NULLS: bool, const NAN_EQUAL: bool> NullableEq
68 for EqualityValue<'_, GROUP_NULLS, NAN_EQUAL, Value>
69{
70 #[inline(always)]
71 fn eq(&self, rhs: &Self) -> Value {
72 let wrap_list = EqualityValue::<'_, { GROUP_NULLS }, { NAN_EQUAL }, List>;
73 let wrap_bag = EqualityValue::<'_, { GROUP_NULLS }, { NAN_EQUAL }, Bag>;
74 let wrap_tuple = EqualityValue::<'_, { GROUP_NULLS }, { NAN_EQUAL }, Tuple>;
75 let wrap_var = EqualityValue::<'_, { GROUP_NULLS }, { NAN_EQUAL }, Variant>;
76 if GROUP_NULLS {
77 if let (Value::Missing | Value::Null, Value::Missing | Value::Null) = (self.0, rhs.0) {
78 return Value::Boolean(true);
79 }
80 } else if matches!(self.0, Value::Missing) || matches!(rhs.0, Value::Missing) {
81 return Value::Missing;
82 } else if matches!(self.0, Value::Null) || matches!(rhs.0, Value::Null) {
83 return Value::Null;
84 }
85
86 match (self.0, rhs.0) {
87 (Value::Integer(_), Value::Real(_)) => {
88 Value::from(&util::coerce_int_to_real(self.0) == rhs.0)
89 }
90 (Value::Integer(_), Value::Decimal(_)) => {
91 Value::from(&util::coerce_int_or_real_to_decimal(self.0) == rhs.0)
92 }
93 (Value::Real(_), Value::Decimal(_)) => {
94 Value::from(&util::coerce_int_or_real_to_decimal(self.0) == rhs.0)
95 }
96 (Value::Real(_), Value::Integer(_)) => {
97 Value::from(self.0 == &util::coerce_int_to_real(rhs.0))
98 }
99 (Value::Decimal(_), Value::Integer(_)) => {
100 Value::from(self.0 == &util::coerce_int_or_real_to_decimal(rhs.0))
101 }
102 (Value::Decimal(_), Value::Real(_)) => {
103 Value::from(self.0 == &util::coerce_int_or_real_to_decimal(rhs.0))
104 }
105 (Value::Real(l), Value::Real(r)) => {
106 if NAN_EQUAL && l.is_nan() && r.is_nan() {
107 return Value::Boolean(true);
108 }
109 Value::from(l == r)
110 }
111 (Value::List(l), Value::List(r)) => NullableEq::eq(&wrap_list(l), &wrap_list(r)),
112 (Value::Bag(l), Value::Bag(r)) => NullableEq::eq(&wrap_bag(l), &wrap_bag(r)),
113 (Value::Tuple(l), Value::Tuple(r)) => NullableEq::eq(&wrap_tuple(l), &wrap_tuple(r)),
114 (Value::Variant(l), Value::Variant(r)) => NullableEq::eq(&wrap_var(l), &wrap_var(r)),
115 (_, _) => Value::from(self.0 == rhs.0),
116 }
117 }
118
119 #[inline(always)]
120 fn eqg(&self, rhs: &Self) -> Value {
121 let wrap = EqualityValue::<'_, true, { NAN_EQUAL }, _>;
122 NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
123 }
124}
125
126pub trait NullableOrd {
128 type Output;
129
130 fn lt(&self, rhs: &Self) -> Self::Output;
131 fn gt(&self, rhs: &Self) -> Self::Output;
132 fn lteq(&self, rhs: &Self) -> Self::Output;
133 fn gteq(&self, rhs: &Self) -> Self::Output;
134}
135
136impl NullableOrd for Value {
137 type Output = Self;
138
139 fn lt(&self, rhs: &Self) -> Self::Output {
140 match (self, rhs) {
141 (Value::Missing, _) => Value::Missing,
142 (_, Value::Missing) => Value::Missing,
143 (Value::Null, _) => Value::Null,
144 (_, Value::Null) => Value::Null,
145 (_, _) => {
146 if self.is_comparable_to(rhs) {
147 Value::from(self < rhs)
148 } else {
149 Value::Missing
150 }
151 }
152 }
153 }
154
155 fn gt(&self, rhs: &Self) -> Self::Output {
156 match (self, rhs) {
157 (Value::Missing, _) => Value::Missing,
158 (_, Value::Missing) => Value::Missing,
159 (Value::Null, _) => Value::Null,
160 (_, Value::Null) => Value::Null,
161 (_, _) => {
162 if self.is_comparable_to(rhs) {
163 Value::from(self > rhs)
164 } else {
165 Value::Missing
166 }
167 }
168 }
169 }
170
171 fn lteq(&self, rhs: &Self) -> Self::Output {
172 match (self, rhs) {
173 (Value::Missing, _) => Value::Missing,
174 (_, Value::Missing) => Value::Missing,
175 (Value::Null, _) => Value::Null,
176 (_, Value::Null) => Value::Null,
177 (_, _) => {
178 if self.is_comparable_to(rhs) {
179 Value::from(self <= rhs)
180 } else {
181 Value::Missing
182 }
183 }
184 }
185 }
186
187 fn gteq(&self, rhs: &Self) -> Self::Output {
188 match (self, rhs) {
189 (Value::Missing, _) => Value::Missing,
190 (_, Value::Missing) => Value::Missing,
191 (Value::Null, _) => Value::Null,
192 (_, Value::Null) => Value::Null,
193 (_, _) => {
194 if self.is_comparable_to(rhs) {
195 Value::from(self >= rhs)
196 } else {
197 Value::Missing
198 }
199 }
200 }
201 }
202}