use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::error::Result;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Operator {
And,
Or,
Not,
}
impl Operator {
pub fn as_str(&self) -> &'static str {
match self {
Self::And => "and",
Self::Or => "or",
Self::Not => "not",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Comparator {
Eq,
Ne,
Gt,
Gte,
Lt,
Lte,
Contain,
Like,
In,
Nin,
}
impl Comparator {
pub fn as_str(&self) -> &'static str {
match self {
Self::Eq => "eq",
Self::Ne => "ne",
Self::Gt => "gt",
Self::Gte => "gte",
Self::Lt => "lt",
Self::Lte => "lte",
Self::Contain => "contain",
Self::Like => "like",
Self::In => "in",
Self::Nin => "nin",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Comparison {
pub comparator: Comparator,
pub attribute: String,
pub value: Value,
}
impl Comparison {
pub fn new(comparator: Comparator, attribute: impl Into<String>, value: Value) -> Self {
Self {
comparator,
attribute: attribute.into(),
value,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Operation {
pub operator: Operator,
pub arguments: Vec<FilterDirective>,
}
impl Operation {
pub fn new(operator: Operator, arguments: Vec<FilterDirective>) -> Self {
Self {
operator,
arguments,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum FilterDirective {
Comparison(Comparison),
Operation(Operation),
}
impl FilterDirective {
pub fn accept(&self, visitor: &dyn Visitor) -> Result<Value> {
match self {
Self::Comparison(c) => visitor.visit_comparison(c),
Self::Operation(o) => visitor.visit_operation(o),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StructuredQuery {
pub query: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub filter: Option<FilterDirective>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub limit: Option<usize>,
}
impl StructuredQuery {
pub fn new(query: impl Into<String>) -> Self {
Self {
query: query.into(),
filter: None,
limit: None,
}
}
pub fn with_filter(mut self, filter: FilterDirective) -> Self {
self.filter = Some(filter);
self
}
pub fn with_limit(mut self, limit: usize) -> Self {
self.limit = Some(limit);
self
}
}
pub trait Visitor: Send + Sync {
fn allowed_comparators(&self) -> &[Comparator];
fn allowed_operators(&self) -> &[Operator];
fn visit_comparison(&self, comparison: &Comparison) -> Result<Value>;
fn visit_operation(&self, operation: &Operation) -> Result<Value>;
fn visit_structured_query(&self, query: &StructuredQuery) -> Result<(String, Value)>;
}