1use std::marker::PhantomData;
11
12use serde_json::{Map, Value};
13
14use super::{
15 Common, FlussoValue, RangeRelation, Sort, SortOrder, common_opts, exists_q, kind, single, wrap,
16};
17use crate::query::{AsQuery, Query, Root};
18
19fn date_value(value: &impl FlussoValue<kind::Date>) -> Value {
24 match serde_json::to_value(value) {
25 Ok(Value::String(string)) => Value::String(string),
26 Ok(other) => Value::String(other.to_string()),
27 Err(_) => Value::String(String::new()),
28 }
29}
30
31fn number_value<K>(value: &impl FlussoValue<K>) -> Value {
37 match serde_json::to_value(value) {
38 Ok(Value::String(string)) => string
39 .parse::<serde_json::Number>()
40 .map_or(Value::String(string), Value::Number),
41 Ok(other) => other,
42 Err(_) => Value::Null,
43 }
44}
45
46fn bool_value(value: &impl FlussoValue<kind::Bool>) -> Value {
49 serde_json::to_value(value).unwrap_or(Value::Null)
50}
51
52#[derive(Debug, Clone)]
55pub struct EqQuery<S = Root> {
56 path: String,
57 value: Value,
58 common: Common,
59 _scope: PhantomData<fn() -> S>,
60}
61
62impl<S> EqQuery<S> {
63 fn new(path: &str, value: Value) -> Self {
64 Self {
65 path: path.to_string(),
66 value,
67 common: Common::default(),
68 _scope: PhantomData,
69 }
70 }
71
72 common_opts!(common);
73}
74
75impl<S> AsQuery<S> for EqQuery<S> {
76 fn into_query(self) -> Option<Query<S>> {
77 if self.common.is_empty() {
78 Some(single("term", &self.path, self.value))
79 } else {
80 let mut body = Map::new();
81 body.insert("value".to_string(), self.value);
82 self.common.write(&mut body);
83 Some(single("term", &self.path, Value::Object(body)))
84 }
85 }
86}
87
88#[derive(Debug, Clone)]
91pub struct TermsQuery<S = Root> {
92 path: String,
93 values: Vec<Value>,
94 common: Common,
95 _scope: PhantomData<fn() -> S>,
96}
97
98impl<S> TermsQuery<S> {
99 pub(crate) fn new(path: &str, values: Vec<Value>) -> Self {
100 Self {
101 path: path.to_string(),
102 values,
103 common: Common::default(),
104 _scope: PhantomData,
105 }
106 }
107
108 common_opts!(common);
109}
110
111impl<S> AsQuery<S> for TermsQuery<S> {
112 fn into_query(self) -> Option<Query<S>> {
113 let mut body = Map::new();
115 body.insert(self.path, Value::Array(self.values));
116 self.common.write(&mut body);
117 Some(wrap("terms", body))
118 }
119}
120
121#[derive(Debug, Clone)]
124pub struct RangeQuery<S = Root> {
125 path: String,
126 bounds: Vec<(&'static str, Value)>,
127 extra: Map<String, Value>,
128 common: Common,
129 _scope: PhantomData<fn() -> S>,
130}
131
132impl<S> RangeQuery<S> {
133 pub(crate) fn new(path: &str, bounds: Vec<(&'static str, Value)>) -> Self {
134 Self {
135 path: path.to_string(),
136 bounds,
137 extra: Map::new(),
138 common: Common::default(),
139 _scope: PhantomData,
140 }
141 }
142
143 #[must_use]
145 pub fn format(mut self, format: impl Into<String>) -> Self {
146 self.extra
147 .insert("format".to_string(), Value::String(format.into()));
148 self
149 }
150
151 #[must_use]
153 pub fn time_zone(mut self, time_zone: impl Into<String>) -> Self {
154 self.extra
155 .insert("time_zone".to_string(), Value::String(time_zone.into()));
156 self
157 }
158
159 #[must_use]
162 pub fn relation(mut self, relation: RangeRelation) -> Self {
163 self.extra.insert(
164 "relation".to_string(),
165 Value::String(relation.as_str().to_string()),
166 );
167 self
168 }
169
170 common_opts!(common);
171}
172
173impl<S> AsQuery<S> for RangeQuery<S> {
174 fn into_query(self) -> Option<Query<S>> {
175 let mut body = self.extra;
176 for (key, value) in self.bounds {
177 body.insert(key.to_string(), value);
178 }
179 self.common.write(&mut body);
180 Some(single("range", &self.path, Value::Object(body)))
181 }
182}
183
184#[derive(Debug, Clone)]
186pub struct Bool<S = Root> {
187 path: String,
188 _scope: PhantomData<fn() -> S>,
189}
190
191impl<S> Bool<S> {
192 pub fn at(path: impl Into<String>) -> Self {
193 Self {
194 path: path.into(),
195 _scope: PhantomData,
196 }
197 }
198
199 pub fn eq(&self, value: impl FlussoValue<kind::Bool>) -> EqQuery<S> {
201 EqQuery::new(&self.path, bool_value(&value))
202 }
203
204 pub fn exists(&self) -> Query<S> {
206 exists_q(&self.path)
207 }
208
209 pub fn asc(&self) -> Sort {
210 Sort::new(&self.path, SortOrder::Asc)
211 }
212
213 pub fn desc(&self) -> Sort {
214 Sort::new(&self.path, SortOrder::Desc)
215 }
216}
217
218#[derive(Debug, Clone)]
226pub struct Number<K, S = Root> {
227 path: String,
228 _marker: PhantomData<fn() -> (K, S)>,
229}
230
231impl<K, S> Number<K, S> {
232 pub fn at(path: impl Into<String>) -> Self {
233 Self {
234 path: path.into(),
235 _marker: PhantomData,
236 }
237 }
238
239 pub fn eq(&self, value: impl FlussoValue<K>) -> EqQuery<S> {
241 EqQuery::new(&self.path, number_value(&value))
242 }
243
244 pub fn any_of(&self, values: impl IntoIterator<Item = impl FlussoValue<K>>) -> TermsQuery<S> {
246 let array = values.into_iter().map(|v| number_value(&v)).collect();
247 TermsQuery::new(&self.path, array)
248 }
249
250 pub fn lt(&self, value: impl FlussoValue<K>) -> RangeQuery<S> {
252 RangeQuery::new(&self.path, vec![("lt", number_value(&value))])
253 }
254
255 pub fn lte(&self, value: impl FlussoValue<K>) -> RangeQuery<S> {
257 RangeQuery::new(&self.path, vec![("lte", number_value(&value))])
258 }
259
260 pub fn gt(&self, value: impl FlussoValue<K>) -> RangeQuery<S> {
262 RangeQuery::new(&self.path, vec![("gt", number_value(&value))])
263 }
264
265 pub fn gte(&self, value: impl FlussoValue<K>) -> RangeQuery<S> {
267 RangeQuery::new(&self.path, vec![("gte", number_value(&value))])
268 }
269
270 pub fn between(&self, low: impl FlussoValue<K>, high: impl FlussoValue<K>) -> RangeQuery<S> {
272 RangeQuery::new(
273 &self.path,
274 vec![("gte", number_value(&low)), ("lte", number_value(&high))],
275 )
276 }
277
278 pub fn exists(&self) -> Query<S> {
280 exists_q(&self.path)
281 }
282
283 pub fn asc(&self) -> Sort {
284 Sort::new(&self.path, SortOrder::Asc)
285 }
286
287 pub fn desc(&self) -> Sort {
288 Sort::new(&self.path, SortOrder::Desc)
289 }
290}
291
292#[derive(Debug, Clone)]
294pub struct Date<S = Root> {
295 path: String,
296 _scope: PhantomData<fn() -> S>,
297}
298
299impl<S> Date<S> {
300 pub fn at(path: impl Into<String>) -> Self {
301 Self {
302 path: path.into(),
303 _scope: PhantomData,
304 }
305 }
306
307 pub fn eq(&self, value: impl FlussoValue<kind::Date>) -> EqQuery<S> {
310 EqQuery::new(&self.path, date_value(&value))
311 }
312
313 pub fn any_of(
315 &self,
316 values: impl IntoIterator<Item = impl FlussoValue<kind::Date>>,
317 ) -> TermsQuery<S> {
318 let array = values.into_iter().map(|v| date_value(&v)).collect();
319 TermsQuery::new(&self.path, array)
320 }
321
322 pub fn lt(&self, value: impl FlussoValue<kind::Date>) -> RangeQuery<S> {
324 RangeQuery::new(&self.path, vec![("lt", date_value(&value))])
325 }
326
327 pub fn lte(&self, value: impl FlussoValue<kind::Date>) -> RangeQuery<S> {
329 RangeQuery::new(&self.path, vec![("lte", date_value(&value))])
330 }
331
332 pub fn gt(&self, value: impl FlussoValue<kind::Date>) -> RangeQuery<S> {
334 RangeQuery::new(&self.path, vec![("gt", date_value(&value))])
335 }
336
337 pub fn gte(&self, value: impl FlussoValue<kind::Date>) -> RangeQuery<S> {
339 RangeQuery::new(&self.path, vec![("gte", date_value(&value))])
340 }
341
342 pub fn between(
344 &self,
345 low: impl FlussoValue<kind::Date>,
346 high: impl FlussoValue<kind::Date>,
347 ) -> RangeQuery<S> {
348 RangeQuery::new(
349 &self.path,
350 vec![("gte", date_value(&low)), ("lte", date_value(&high))],
351 )
352 }
353
354 pub fn exists(&self) -> Query<S> {
356 exists_q(&self.path)
357 }
358
359 pub fn asc(&self) -> Sort {
360 Sort::new(&self.path, SortOrder::Asc)
361 }
362
363 pub fn desc(&self) -> Sort {
364 Sort::new(&self.path, SortOrder::Desc)
365 }
366}