use std::marker::PhantomData;
use serde_json::{Map, Value};
use super::{Common, Sort, SortOrder, common_opts, exists_q, single, wrap};
use crate::query::{AsQuery, Query, Root};
#[derive(Debug, Clone)]
pub struct EqQuery<S = Root> {
path: String,
value: Value,
common: Common,
_scope: PhantomData<fn() -> S>,
}
impl<S> EqQuery<S> {
fn new(path: &str, value: Value) -> Self {
Self {
path: path.to_string(),
value,
common: Common::default(),
_scope: PhantomData,
}
}
common_opts!(common);
}
impl<S> AsQuery<S> for EqQuery<S> {
fn into_query(self) -> Option<Query<S>> {
if self.common.is_empty() {
Some(single("term", &self.path, self.value))
} else {
let mut body = Map::new();
body.insert("value".to_string(), self.value);
self.common.write(&mut body);
Some(single("term", &self.path, Value::Object(body)))
}
}
}
#[derive(Debug, Clone)]
pub struct TermsQuery<S = Root> {
path: String,
values: Vec<Value>,
common: Common,
_scope: PhantomData<fn() -> S>,
}
impl<S> TermsQuery<S> {
pub(crate) fn new(path: &str, values: Vec<Value>) -> Self {
Self {
path: path.to_string(),
values,
common: Common::default(),
_scope: PhantomData,
}
}
common_opts!(common);
}
impl<S> AsQuery<S> for TermsQuery<S> {
fn into_query(self) -> Option<Query<S>> {
let mut body = Map::new();
body.insert(self.path, Value::Array(self.values));
self.common.write(&mut body);
Some(wrap("terms", body))
}
}
#[derive(Debug, Clone)]
pub struct RangeQuery<S = Root> {
path: String,
bounds: Vec<(&'static str, Value)>,
extra: Map<String, Value>,
common: Common,
_scope: PhantomData<fn() -> S>,
}
impl<S> RangeQuery<S> {
pub(crate) fn new(path: &str, bounds: Vec<(&'static str, Value)>) -> Self {
Self {
path: path.to_string(),
bounds,
extra: Map::new(),
common: Common::default(),
_scope: PhantomData,
}
}
#[must_use]
pub fn format(mut self, format: impl Into<String>) -> Self {
self.extra
.insert("format".to_string(), Value::String(format.into()));
self
}
#[must_use]
pub fn time_zone(mut self, time_zone: impl Into<String>) -> Self {
self.extra
.insert("time_zone".to_string(), Value::String(time_zone.into()));
self
}
#[must_use]
pub fn relation(mut self, relation: impl Into<String>) -> Self {
self.extra
.insert("relation".to_string(), Value::String(relation.into()));
self
}
common_opts!(common);
}
impl<S> AsQuery<S> for RangeQuery<S> {
fn into_query(self) -> Option<Query<S>> {
let mut body = self.extra;
for (key, value) in self.bounds {
body.insert(key.to_string(), value);
}
self.common.write(&mut body);
Some(single("range", &self.path, Value::Object(body)))
}
}
#[derive(Debug, Clone)]
pub struct Bool<S = Root> {
path: String,
_scope: PhantomData<fn() -> S>,
}
impl<S> Bool<S> {
pub fn at(path: impl Into<String>) -> Self {
Self {
path: path.into(),
_scope: PhantomData,
}
}
pub fn eq(&self, value: bool) -> EqQuery<S> {
EqQuery::new(&self.path, Value::Bool(value))
}
pub fn exists(&self) -> Query<S> {
exists_q(&self.path)
}
}
#[derive(Debug, Clone)]
pub struct Number<T, S = Root> {
path: String,
_marker: PhantomData<fn() -> (T, S)>,
}
impl<T, S> Number<T, S>
where
T: Into<Value> + Copy,
{
pub fn at(path: impl Into<String>) -> Self {
Self {
path: path.into(),
_marker: PhantomData,
}
}
pub fn eq(&self, value: T) -> EqQuery<S> {
EqQuery::new(&self.path, value.into())
}
pub fn in_(&self, values: impl IntoIterator<Item = T>) -> TermsQuery<S> {
let array = values.into_iter().map(Into::into).collect();
TermsQuery::new(&self.path, array)
}
pub fn lt(&self, value: T) -> RangeQuery<S> {
RangeQuery::new(&self.path, vec![("lt", value.into())])
}
pub fn lte(&self, value: T) -> RangeQuery<S> {
RangeQuery::new(&self.path, vec![("lte", value.into())])
}
pub fn gt(&self, value: T) -> RangeQuery<S> {
RangeQuery::new(&self.path, vec![("gt", value.into())])
}
pub fn gte(&self, value: T) -> RangeQuery<S> {
RangeQuery::new(&self.path, vec![("gte", value.into())])
}
pub fn between(&self, low: T, high: T) -> RangeQuery<S> {
RangeQuery::new(&self.path, vec![("gte", low.into()), ("lte", high.into())])
}
pub fn exists(&self) -> Query<S> {
exists_q(&self.path)
}
pub fn asc(&self) -> Sort {
Sort::new(&self.path, SortOrder::Asc)
}
pub fn desc(&self) -> Sort {
Sort::new(&self.path, SortOrder::Desc)
}
}
#[derive(Debug, Clone)]
pub struct Date<S = Root> {
path: String,
_scope: PhantomData<fn() -> S>,
}
impl<S> Date<S> {
pub fn at(path: impl Into<String>) -> Self {
Self {
path: path.into(),
_scope: PhantomData,
}
}
pub fn eq(&self, value: impl Into<String>) -> EqQuery<S> {
EqQuery::new(&self.path, Value::String(value.into()))
}
pub fn lt(&self, value: impl Into<String>) -> RangeQuery<S> {
RangeQuery::new(&self.path, vec![("lt", Value::String(value.into()))])
}
pub fn lte(&self, value: impl Into<String>) -> RangeQuery<S> {
RangeQuery::new(&self.path, vec![("lte", Value::String(value.into()))])
}
pub fn gt(&self, value: impl Into<String>) -> RangeQuery<S> {
RangeQuery::new(&self.path, vec![("gt", Value::String(value.into()))])
}
pub fn gte(&self, value: impl Into<String>) -> RangeQuery<S> {
RangeQuery::new(&self.path, vec![("gte", Value::String(value.into()))])
}
pub fn between(&self, low: impl Into<String>, high: impl Into<String>) -> RangeQuery<S> {
RangeQuery::new(
&self.path,
vec![
("gte", Value::String(low.into())),
("lte", Value::String(high.into())),
],
)
}
pub fn exists(&self) -> Query<S> {
exists_q(&self.path)
}
pub fn asc(&self) -> Sort {
Sort::new(&self.path, SortOrder::Asc)
}
pub fn desc(&self) -> Sort {
Sort::new(&self.path, SortOrder::Desc)
}
}