cipherstash_config/operator.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
use std::fmt::Debug;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Operator {
Lt,
Lte,
Eq,
Gt,
Gte,
Like,
ILike,
STEVecOperator(STEVecOperator),
Unsupported,
}
/// These are all binary operators (*probably* PG specific).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum STEVecOperator {
LeftContainsRight, // @>
RightContainsLeft, // <@
}
impl Operator {
pub fn as_str(&self) -> &'static str {
match self {
Self::Lt => "<",
Self::Lte => "<=",
Self::Eq => "=",
Self::Gt => ">",
Self::Gte => ">=",
Self::Like => "~~", //Note: This is PostgreSQL specific syntax.
Self::ILike => "~~*", //Note: This PostgreSQL specific syntax.
Self::STEVecOperator(op) => op.as_str(),
// TODO: Probably better to use an Error and handle errors in callers
_ => "unsupported",
}
}
}
impl STEVecOperator {
pub fn as_str(&self) -> &'static str {
match self {
STEVecOperator::LeftContainsRight => "@>",
STEVecOperator::RightContainsLeft => "<@",
// TODO: implement support for the following (which will require creating a custom PG type called ste_vec with operators defined on it)
// The above two operators happen to "just work" because cs_ste_vec_v1 is an array and they are defined for arrays and JSON in PG.
// In the meantime the lack of the following operators can be worked around by converting to `@>` and multiple expressions with logical AND/OR.
// STEVecOperator::LeftIsTopLevelKey => "?",
// STEVecOperator::AnyOfLeftIsTopLevelKey => "?|",
// STEVecOperator::AllOfLeftIsTopLevelKey => "?&",
}
}
}
impl From<&str> for Operator {
fn from(value: &str) -> Self {
match value {
"<" => Self::Lt,
"<=" => Self::Lte,
"=" => Self::Eq,
">" => Self::Gt,
">=" => Self::Gte,
"~~" => Self::Like,
"~~*" => Self::ILike,
"@>" => Self::STEVecOperator(STEVecOperator::LeftContainsRight),
"<@" => Self::STEVecOperator(STEVecOperator::RightContainsLeft),
_ => Self::Unsupported,
}
}
}
impl From<String> for Operator {
fn from(value: String) -> Self {
value.as_str().into()
}
}
impl From<Vec<String>> for Operator {
fn from(value: Vec<String>) -> Self {
if value.len() == 1 {
value[0].to_string().into()
} else {
Self::Unsupported
}
}
}
impl std::fmt::Display for Operator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let text = match self {
Self::Lt => "<",
Self::Lte => "<=",
Self::Eq => "==",
Self::Gt => ">",
Self::Gte => ">=",
Self::Like => "LIKE",
Self::ILike => "ILIKE",
Self::STEVecOperator(op) => op.as_str(),
Self::Unsupported => "Unsupported",
};
write!(f, "{text}")
}
}