use crate::expr_fn::binary_expr;
use crate::Expr;
use std::fmt;
use std::ops;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Hash)]
pub enum Operator {
Eq,
NotEq,
Lt,
LtEq,
Gt,
GtEq,
Plus,
Minus,
Multiply,
Divide,
Modulo,
And,
Or,
IsDistinctFrom,
IsNotDistinctFrom,
RegexMatch,
RegexIMatch,
RegexNotMatch,
RegexNotIMatch,
BitwiseAnd,
BitwiseOr,
BitwiseXor,
BitwiseShiftRight,
BitwiseShiftLeft,
StringConcat,
}
impl Operator {
pub fn negate(&self) -> Option<Operator> {
match self {
Operator::Eq => Some(Operator::NotEq),
Operator::NotEq => Some(Operator::Eq),
Operator::Lt => Some(Operator::GtEq),
Operator::LtEq => Some(Operator::Gt),
Operator::Gt => Some(Operator::LtEq),
Operator::GtEq => Some(Operator::Lt),
Operator::IsDistinctFrom => Some(Operator::IsNotDistinctFrom),
Operator::IsNotDistinctFrom => Some(Operator::IsDistinctFrom),
Operator::Plus
| Operator::Minus
| Operator::Multiply
| Operator::Divide
| Operator::Modulo
| Operator::And
| Operator::Or
| Operator::RegexMatch
| Operator::RegexIMatch
| Operator::RegexNotMatch
| Operator::RegexNotIMatch
| Operator::BitwiseAnd
| Operator::BitwiseOr
| Operator::BitwiseXor
| Operator::BitwiseShiftRight
| Operator::BitwiseShiftLeft
| Operator::StringConcat => None,
}
}
pub fn swap(&self) -> Option<Operator> {
match self {
Operator::Eq => Some(Operator::Eq),
Operator::NotEq => Some(Operator::NotEq),
Operator::Lt => Some(Operator::Gt),
Operator::LtEq => Some(Operator::GtEq),
Operator::Gt => Some(Operator::Lt),
Operator::GtEq => Some(Operator::LtEq),
Operator::IsDistinctFrom
| Operator::IsNotDistinctFrom
| Operator::Plus
| Operator::Minus
| Operator::Multiply
| Operator::Divide
| Operator::Modulo
| Operator::And
| Operator::Or
| Operator::RegexMatch
| Operator::RegexIMatch
| Operator::RegexNotMatch
| Operator::RegexNotIMatch
| Operator::BitwiseAnd
| Operator::BitwiseOr
| Operator::BitwiseXor
| Operator::BitwiseShiftRight
| Operator::BitwiseShiftLeft
| Operator::StringConcat => None,
}
}
}
impl fmt::Display for Operator {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let display = match &self {
Operator::Eq => "=",
Operator::NotEq => "!=",
Operator::Lt => "<",
Operator::LtEq => "<=",
Operator::Gt => ">",
Operator::GtEq => ">=",
Operator::Plus => "+",
Operator::Minus => "-",
Operator::Multiply => "*",
Operator::Divide => "/",
Operator::Modulo => "%",
Operator::And => "AND",
Operator::Or => "OR",
Operator::RegexMatch => "~",
Operator::RegexIMatch => "~*",
Operator::RegexNotMatch => "!~",
Operator::RegexNotIMatch => "!~*",
Operator::IsDistinctFrom => "IS DISTINCT FROM",
Operator::IsNotDistinctFrom => "IS NOT DISTINCT FROM",
Operator::BitwiseAnd => "&",
Operator::BitwiseOr => "|",
Operator::BitwiseXor => "#",
Operator::BitwiseShiftRight => ">>",
Operator::BitwiseShiftLeft => "<<",
Operator::StringConcat => "||",
};
write!(f, "{display}")
}
}
impl ops::Add for Expr {
type Output = Self;
fn add(self, rhs: Self) -> Self {
binary_expr(self, Operator::Plus, rhs)
}
}
impl ops::Sub for Expr {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
binary_expr(self, Operator::Minus, rhs)
}
}
impl ops::Mul for Expr {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
binary_expr(self, Operator::Multiply, rhs)
}
}
impl ops::Div for Expr {
type Output = Self;
fn div(self, rhs: Self) -> Self {
binary_expr(self, Operator::Divide, rhs)
}
}
impl ops::Rem for Expr {
type Output = Self;
fn rem(self, rhs: Self) -> Self {
binary_expr(self, Operator::Modulo, rhs)
}
}
#[cfg(test)]
mod tests {
use crate::lit;
#[test]
fn test_operators() {
assert_eq!(
format!("{:?}", lit(1u32) + lit(2u32)),
"UInt32(1) + UInt32(2)"
);
assert_eq!(
format!("{:?}", lit(1u32) - lit(2u32)),
"UInt32(1) - UInt32(2)"
);
assert_eq!(
format!("{:?}", lit(1u32) * lit(2u32)),
"UInt32(1) * UInt32(2)"
);
assert_eq!(
format!("{:?}", lit(1u32) / lit(2u32)),
"UInt32(1) / UInt32(2)"
);
assert_eq!(
format!("{:?}", lit(1u32) % lit(2u32)),
"UInt32(1) % UInt32(2)"
);
}
}