1use serde::{Deserialize, Serialize};
13
14use crate::Method;
15
16use super::{request::ResultReference, Object, RequestParams};
17
18pub trait QueryObject: Object {
19 type QueryArguments: Default + Serialize;
20 type Filter: Serialize;
21 type Sort: Serialize;
22}
23
24#[derive(Debug, Clone, Serialize)]
25pub struct QueryRequest<O: QueryObject> {
26 #[serde(skip)]
27 method: (Method, usize),
28
29 #[serde(rename = "accountId")]
30 account_id: String,
31
32 #[serde(rename = "filter")]
33 #[serde(skip_serializing_if = "Option::is_none")]
34 filter: Option<Filter<O::Filter>>,
35
36 #[serde(rename = "sort")]
37 #[serde(skip_serializing_if = "Option::is_none")]
38 sort: Option<Vec<Comparator<O::Sort>>>,
39
40 #[serde(rename = "position")]
41 #[serde(skip_serializing_if = "Option::is_none")]
42 position: Option<i32>,
43
44 #[serde(rename = "anchor")]
45 #[serde(skip_serializing_if = "Option::is_none")]
46 anchor: Option<String>,
47
48 #[serde(rename = "anchorOffset")]
49 #[serde(skip_serializing_if = "Option::is_none")]
50 anchor_offset: Option<i32>,
51
52 #[serde(rename = "limit")]
53 #[serde(skip_serializing_if = "Option::is_none")]
54 limit: Option<usize>,
55
56 #[serde(rename = "calculateTotal")]
57 #[serde(skip_serializing_if = "Option::is_none")]
58 calculate_total: Option<bool>,
59
60 #[serde(flatten)]
61 arguments: O::QueryArguments,
62}
63
64#[derive(Debug, Clone, Serialize)]
65#[serde(untagged)]
66pub enum Filter<T> {
67 FilterOperator(FilterOperator<T>),
68 FilterCondition(T),
69}
70
71#[derive(Debug, Clone, Serialize)]
72pub struct FilterOperator<T> {
73 operator: Operator,
74 conditions: Vec<Filter<T>>,
75}
76
77#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
78pub enum Operator {
79 #[serde(rename = "AND")]
80 And,
81 #[serde(rename = "OR")]
82 Or,
83 #[serde(rename = "NOT")]
84 Not,
85}
86
87#[derive(Debug, Clone, Serialize)]
88pub struct Comparator<A> {
89 #[serde(rename = "isAscending")]
90 is_ascending: bool,
91
92 #[serde(skip_serializing_if = "Option::is_none")]
93 collation: Option<String>,
94
95 #[serde(flatten)]
96 arguments: A,
97}
98
99#[derive(Debug, Clone, Deserialize)]
100pub struct QueryResponse {
101 #[serde(rename = "accountId")]
102 account_id: String,
103
104 #[serde(rename = "queryState")]
105 query_state: String,
106
107 #[serde(rename = "canCalculateChanges")]
108 can_calculate_changes: Option<bool>,
109
110 #[serde(rename = "position")]
111 position: i32,
112
113 #[serde(rename = "ids")]
114 ids: Vec<String>,
115
116 #[serde(rename = "total")]
117 total: Option<usize>,
118
119 #[serde(rename = "limit")]
120 limit: Option<usize>,
121}
122
123impl<O: QueryObject> QueryRequest<O> {
124 pub fn new(params: RequestParams) -> Self {
125 QueryRequest {
126 account_id: params.account_id,
127 method: (params.method, params.call_id),
128 filter: None,
129 sort: None,
130 position: None,
131 anchor: None,
132 anchor_offset: None,
133 limit: None,
134 calculate_total: None,
135 arguments: O::QueryArguments::default(),
136 }
137 }
138
139 pub fn account_id(&mut self, account_id: impl Into<String>) -> &mut Self {
140 self.account_id = account_id.into();
141 self
142 }
143
144 pub fn filter(&mut self, filter: impl Into<Filter<O::Filter>>) -> &mut Self {
145 self.filter = Some(filter.into());
146 self
147 }
148
149 pub fn sort(&mut self, sort: impl IntoIterator<Item = Comparator<O::Sort>>) -> &mut Self {
150 self.sort = Some(sort.into_iter().collect());
151 self
152 }
153
154 pub fn position(&mut self, position: i32) -> &mut Self {
155 self.position = position.into();
156 self
157 }
158
159 pub fn anchor(&mut self, anchor: impl Into<String>) -> &mut Self {
160 self.anchor = Some(anchor.into());
161 self
162 }
163
164 pub fn anchor_offset(&mut self, anchor_offset: i32) -> &mut Self {
165 self.anchor_offset = anchor_offset.into();
166 self
167 }
168
169 pub fn limit(&mut self, limit: usize) -> &mut Self {
170 self.limit = Some(limit);
171 self
172 }
173
174 pub fn calculate_total(&mut self, calculate_total: bool) -> &mut Self {
175 self.calculate_total = Some(calculate_total);
176 self
177 }
178
179 pub fn arguments(&mut self) -> &mut O::QueryArguments {
180 &mut self.arguments
181 }
182
183 pub fn result_reference(&self) -> ResultReference {
184 ResultReference::new(self.method.0, self.method.1, "/ids")
185 }
186}
187
188impl QueryResponse {
189 pub fn account_id(&self) -> &str {
190 &self.account_id
191 }
192
193 pub fn ids(&self) -> &[String] {
194 &self.ids
195 }
196
197 pub fn id(&self, pos: usize) -> &str {
198 self.ids[pos].as_str()
199 }
200
201 pub fn take_ids(&mut self) -> Vec<String> {
202 std::mem::take(&mut self.ids)
203 }
204
205 pub fn total(&self) -> Option<usize> {
206 self.total
207 }
208
209 pub fn limit(&self) -> Option<usize> {
210 self.limit
211 }
212
213 pub fn position(&self) -> i32 {
214 self.position
215 }
216
217 pub fn take_query_state(&mut self) -> String {
218 std::mem::take(&mut self.query_state)
219 }
220
221 pub fn query_state(&self) -> &str {
222 &self.query_state
223 }
224
225 pub fn can_calculate_changes(&self) -> bool {
226 self.can_calculate_changes.unwrap_or(false)
227 }
228}
229
230impl<A> Comparator<A> {
231 pub fn new(arguments: A) -> Self {
232 Comparator {
233 is_ascending: true,
234 collation: None,
235 arguments,
236 }
237 }
238
239 pub fn descending(mut self) -> Self {
240 self.is_ascending = false;
241 self
242 }
243
244 pub fn ascending(mut self) -> Self {
245 self.is_ascending = true;
246 self
247 }
248
249 pub fn is_ascending(mut self, is_ascending: bool) -> Self {
250 self.is_ascending = is_ascending;
251 self
252 }
253
254 pub fn collation(mut self, collation: String) -> Self {
255 self.collation = Some(collation);
256 self
257 }
258}
259
260impl<T> From<FilterOperator<T>> for Filter<T> {
261 fn from(filter: FilterOperator<T>) -> Self {
262 Filter::FilterOperator(filter)
263 }
264}
265
266impl<T> From<T> for Filter<T> {
267 fn from(filter: T) -> Self {
268 Filter::FilterCondition(filter)
269 }
270}
271
272impl<T> Filter<T> {
273 pub fn operator(operator: Operator, conditions: Vec<Filter<T>>) -> Self {
274 Filter::FilterOperator(FilterOperator {
275 operator,
276 conditions,
277 })
278 }
279
280 pub fn and<U, V>(conditions: U) -> Self
281 where
282 U: IntoIterator<Item = V>,
283 V: Into<Filter<T>>,
284 {
285 Filter::FilterOperator(FilterOperator {
286 operator: Operator::And,
287 conditions: conditions.into_iter().map(|t| t.into()).collect(),
288 })
289 }
290
291 pub fn or<U, V>(conditions: U) -> Self
292 where
293 U: IntoIterator<Item = V>,
294 V: Into<Filter<T>>,
295 {
296 Filter::FilterOperator(FilterOperator {
297 operator: Operator::Or,
298 conditions: conditions.into_iter().map(|t| t.into()).collect(),
299 })
300 }
301
302 pub fn not<U, V>(conditions: U) -> Self
303 where
304 U: IntoIterator<Item = V>,
305 V: Into<Filter<T>>,
306 {
307 Filter::FilterOperator(FilterOperator {
308 operator: Operator::Not,
309 conditions: conditions.into_iter().map(|t| t.into()).collect(),
310 })
311 }
312}