use std::{
fmt::{Display, Write as _},
ops::Range,
};
use chrono::NaiveDateTime;
use crate::query::{BooleanOp, Combine, Field, FieldGroup};
pub struct SearchQuery<'q> {
pub(super) buffer: &'q mut String,
}
impl<'q> SearchQuery<'q> {
#[inline]
pub fn init<E: Into<FieldGroup>>(self, initial: E) -> NonEmptySearchQuery<'q> {
self.buffer.clear();
let _ = write!(self.buffer, "{}", initial.into());
NonEmptySearchQuery {
buffer: self.buffer,
}
}
#[inline]
pub fn extend(self) -> Option<NonEmptySearchQuery<'q>> {
if self.buffer.is_empty() {
None
} else {
Some(NonEmptySearchQuery {
buffer: self.buffer,
})
}
}
pub fn init_or_extend<E: Into<FieldGroup>>(
self,
op: BooleanOp,
element: E,
) -> NonEmptySearchQuery<'q> {
if self.buffer.is_empty() {
let _ = write!(self.buffer, "{}", element.into());
NonEmptySearchQuery {
buffer: self.buffer,
}
} else {
let new = NonEmptySearchQuery {
buffer: self.buffer,
};
new.push(op, element.into())
}
}
pub fn clear(self) -> SearchQuery<'q> {
self.buffer.clear();
self
}
}
pub struct NonEmptySearchQuery<'q> {
pub(super) buffer: &'q mut String,
}
impl Display for NonEmptySearchQuery<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.buffer.fmt(f)
}
}
impl<S: AsRef<str>> Combine<Field<S>> for NonEmptySearchQuery<'_> {
fn push(mut self, op: BooleanOp, element: Field<S>) -> Self {
let _ = write!(&mut self.buffer, "{op}{element}");
self
}
}
impl Combine<FieldGroup> for NonEmptySearchQuery<'_> {
fn push(mut self, op: BooleanOp, element: FieldGroup) -> Self {
let _ = write!(&mut self.buffer, "{op}{element}");
self
}
}
impl Combine<Range<NaiveDateTime>> for NonEmptySearchQuery<'_> {
fn push(mut self, op: BooleanOp, element: Range<NaiveDateTime>) -> Self {
let _ = write!(
&mut self.buffer,
"{}submittedDate:[{} TO {}]",
op,
element.start.format("%Y%m%d%H%M"),
element.end.format("%Y%m%d%H%M")
);
self
}
}