1use core::fmt;
5use std::fmt::Display;
6use std::fmt::Formatter;
7
8use vortex_error::VortexError;
9use vortex_error::VortexResult;
10use vortex_error::vortex_bail;
11use vortex_proto::expr::binary_opts::BinaryOp;
12
13use crate::compute;
14
15#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Hash)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22pub enum Operator {
23 Eq,
25 NotEq,
27 Gt,
29 Gte,
31 Lt,
33 Lte,
35 And,
37 Or,
39 Add,
43 Sub,
49 Mul,
51 Div,
53}
54
55impl From<Operator> for i32 {
56 fn from(value: Operator) -> Self {
57 let op: BinaryOp = value.into();
58 op.into()
59 }
60}
61
62impl From<Operator> for BinaryOp {
63 fn from(value: Operator) -> Self {
64 match value {
65 Operator::Eq => BinaryOp::Eq,
66 Operator::NotEq => BinaryOp::NotEq,
67 Operator::Gt => BinaryOp::Gt,
68 Operator::Gte => BinaryOp::Gte,
69 Operator::Lt => BinaryOp::Lt,
70 Operator::Lte => BinaryOp::Lte,
71 Operator::And => BinaryOp::And,
72 Operator::Or => BinaryOp::Or,
73 Operator::Add => BinaryOp::Add,
74 Operator::Sub => BinaryOp::Sub,
75 Operator::Mul => BinaryOp::Mul,
76 Operator::Div => BinaryOp::Div,
77 }
78 }
79}
80
81impl TryFrom<i32> for Operator {
82 type Error = VortexError;
83
84 fn try_from(value: i32) -> Result<Self, Self::Error> {
85 Ok(BinaryOp::try_from(value)?.into())
86 }
87}
88
89impl From<BinaryOp> for Operator {
90 fn from(value: BinaryOp) -> Self {
91 match value {
92 BinaryOp::Eq => Operator::Eq,
93 BinaryOp::NotEq => Operator::NotEq,
94 BinaryOp::Gt => Operator::Gt,
95 BinaryOp::Gte => Operator::Gte,
96 BinaryOp::Lt => Operator::Lt,
97 BinaryOp::Lte => Operator::Lte,
98 BinaryOp::And => Operator::And,
99 BinaryOp::Or => Operator::Or,
100 BinaryOp::Add => Operator::Add,
101 BinaryOp::Sub => Operator::Sub,
102 BinaryOp::Mul => Operator::Mul,
103 BinaryOp::Div => Operator::Div,
104 }
105 }
106}
107
108impl Display for Operator {
109 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
110 let display = match &self {
111 Operator::Eq => "=",
112 Operator::NotEq => "!=",
113 Operator::Gt => ">",
114 Operator::Gte => ">=",
115 Operator::Lt => "<",
116 Operator::Lte => "<=",
117 Operator::And => "and",
118 Operator::Or => "or",
119 Operator::Add => "+",
120 Operator::Sub => "-",
121 Operator::Mul => "*",
122 Operator::Div => "/",
123 };
124 Display::fmt(display, f)
125 }
126}
127
128impl Operator {
129 pub fn inverse(self) -> Option<Self> {
130 match self {
131 Operator::Eq => Some(Operator::NotEq),
132 Operator::NotEq => Some(Operator::Eq),
133 Operator::Gt => Some(Operator::Lte),
134 Operator::Gte => Some(Operator::Lt),
135 Operator::Lt => Some(Operator::Gte),
136 Operator::Lte => Some(Operator::Gt),
137 Operator::And
138 | Operator::Or
139 | Operator::Add
140 | Operator::Sub
141 | Operator::Mul
142 | Operator::Div => None,
143 }
144 }
145
146 pub fn logical_inverse(self) -> Option<Self> {
147 match self {
148 Operator::And => Some(Operator::Or),
149 Operator::Or => Some(Operator::And),
150 _ => None,
151 }
152 }
153
154 pub fn swap(self) -> Option<Self> {
156 match self {
157 Operator::Eq => Some(Operator::Eq),
158 Operator::NotEq => Some(Operator::NotEq),
159 Operator::Gt => Some(Operator::Lt),
160 Operator::Gte => Some(Operator::Lte),
161 Operator::Lt => Some(Operator::Gt),
162 Operator::Lte => Some(Operator::Gte),
163 Operator::And => Some(Operator::And),
164 Operator::Or => Some(Operator::Or),
165 Operator::Add => Some(Operator::Add),
166 Operator::Mul => Some(Operator::Mul),
167 Operator::Sub | Operator::Div => None,
168 }
169 }
170
171 pub fn maybe_cmp_operator(self) -> Option<compute::Operator> {
172 match self {
173 Operator::Eq => Some(compute::Operator::Eq),
174 Operator::NotEq => Some(compute::Operator::NotEq),
175 Operator::Lt => Some(compute::Operator::Lt),
176 Operator::Lte => Some(compute::Operator::Lte),
177 Operator::Gt => Some(compute::Operator::Gt),
178 Operator::Gte => Some(compute::Operator::Gte),
179 _ => None,
180 }
181 }
182
183 pub fn is_arithmetic(&self) -> bool {
184 matches!(self, Self::Add | Self::Sub | Self::Mul | Self::Div)
185 }
186}
187
188impl From<compute::Operator> for Operator {
189 fn from(cmp_operator: compute::Operator) -> Self {
190 match cmp_operator {
191 compute::Operator::Eq => Operator::Eq,
192 compute::Operator::NotEq => Operator::NotEq,
193 compute::Operator::Gt => Operator::Gt,
194 compute::Operator::Gte => Operator::Gte,
195 compute::Operator::Lt => Operator::Lt,
196 compute::Operator::Lte => Operator::Lte,
197 }
198 }
199}
200
201impl TryInto<compute::Operator> for Operator {
202 type Error = VortexError;
203
204 fn try_into(self) -> VortexResult<compute::Operator> {
205 Ok(match self {
206 Operator::Eq => compute::Operator::Eq,
207 Operator::NotEq => compute::Operator::NotEq,
208 Operator::Gt => compute::Operator::Gt,
209 Operator::Gte => compute::Operator::Gte,
210 Operator::Lt => compute::Operator::Lt,
211 Operator::Lte => compute::Operator::Lte,
212 _ => vortex_bail!("Not a compute operator: {}", self),
213 })
214 }
215}