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