pub mod filter;
use crate::error::CoreError;
use crate::error::CoreError::Unsupported;
use std::cmp::PartialEq;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ExprOperator {
Eq,
Ne,
Lt,
Lte,
Gt,
Gte,
In,
NotIn,
}
impl Display for ExprOperator {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
ExprOperator::Eq => write!(f, "="),
ExprOperator::Ne => write!(f, "!="),
ExprOperator::Lt => write!(f, "<"),
ExprOperator::Lte => write!(f, "<="),
ExprOperator::Gt => write!(f, ">"),
ExprOperator::Gte => write!(f, ">="),
ExprOperator::In => write!(f, "IN"),
ExprOperator::NotIn => write!(f, "NOT IN"),
}
}
}
impl ExprOperator {
pub const TOKEN_OP_PAIRS: [(&'static str, ExprOperator); 8] = [
("=", ExprOperator::Eq),
("!=", ExprOperator::Ne),
("<", ExprOperator::Lt),
("<=", ExprOperator::Lte),
(">", ExprOperator::Gt),
(">=", ExprOperator::Gte),
("IN", ExprOperator::In),
("NOT IN", ExprOperator::NotIn),
];
pub fn is_multi_value(&self) -> bool {
matches!(self, ExprOperator::In | ExprOperator::NotIn)
}
pub fn negate(&self) -> Option<ExprOperator> {
match self {
ExprOperator::Eq => Some(ExprOperator::Ne),
ExprOperator::Ne => Some(ExprOperator::Eq),
ExprOperator::Lt => Some(ExprOperator::Gte),
ExprOperator::Lte => Some(ExprOperator::Gt),
ExprOperator::Gt => Some(ExprOperator::Lte),
ExprOperator::Gte => Some(ExprOperator::Lt),
ExprOperator::In => Some(ExprOperator::NotIn),
ExprOperator::NotIn => Some(ExprOperator::In),
}
}
}
impl FromStr for ExprOperator {
type Err = CoreError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
ExprOperator::TOKEN_OP_PAIRS
.iter()
.find_map(|&(token, op)| {
if token.eq_ignore_ascii_case(s) {
Some(op)
} else {
None
}
})
.ok_or_else(|| Unsupported(format!("Unsupported operator: {s}")))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_operator_from_str() {
assert_eq!(ExprOperator::from_str("=").unwrap(), ExprOperator::Eq);
assert_eq!(ExprOperator::from_str("!=").unwrap(), ExprOperator::Ne);
assert_eq!(ExprOperator::from_str("<").unwrap(), ExprOperator::Lt);
assert_eq!(ExprOperator::from_str("<=").unwrap(), ExprOperator::Lte);
assert_eq!(ExprOperator::from_str(">").unwrap(), ExprOperator::Gt);
assert_eq!(ExprOperator::from_str(">=").unwrap(), ExprOperator::Gte);
assert_eq!(ExprOperator::from_str("IN").unwrap(), ExprOperator::In);
assert_eq!(
ExprOperator::from_str("NOT IN").unwrap(),
ExprOperator::NotIn
);
assert!(ExprOperator::from_str("??").is_err());
}
#[test]
fn test_operator_display() {
assert_eq!(ExprOperator::Eq.to_string(), "=");
assert_eq!(ExprOperator::Ne.to_string(), "!=");
assert_eq!(ExprOperator::Lt.to_string(), "<");
assert_eq!(ExprOperator::Lte.to_string(), "<=");
assert_eq!(ExprOperator::Gt.to_string(), ">");
assert_eq!(ExprOperator::Gte.to_string(), ">=");
assert_eq!(ExprOperator::In.to_string(), "IN");
assert_eq!(ExprOperator::NotIn.to_string(), "NOT IN");
}
}