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