Skip to main content

vn_core/http/query/
json.rs

1use super::FieldSet;
2use crate::error::Result;
3use crate::model::user::UserId;
4use crate::model::{QueryField, SortQueryBy};
5use futures::future::BoxFuture;
6use serde::{Deserialize, Serialize};
7use serde_json::Value as JsonValue;
8use std::borrow::Cow;
9use std::num::NonZeroU16;
10
11type RequestFn<T> = Box<dyn FnOnce(JsonQuery) -> BoxFuture<'static, Result<T>> + Send>;
12
13#[remain::sorted]
14#[derive(Clone, Debug, Default, Deserialize, Serialize)]
15pub struct JsonQuery {
16  compact_filters: bool,
17  count: bool,
18  fields: Option<String>,
19  filters: JsonValue,
20  normalized_filters: bool,
21  page: Option<NonZeroU16>,
22  results: Option<u8>,
23  reverse: bool,
24  sort: Option<String>,
25  user: Option<UserId>,
26}
27
28#[remain::sorted]
29pub struct JsonQueryBuilder<Field, Sort, Value>
30where
31  Field: QueryField,
32  Sort: SortQueryBy,
33  Value: Serialize,
34{
35  compact_filters: bool,
36  count: bool,
37  fields: Option<FieldSet<Field>>,
38  filters: JsonQueryFilter,
39  normalized_filters: bool,
40  page: Option<NonZeroU16>,
41  results: Option<u8>,
42  reverse: bool,
43  send_request: RequestFn<Value>,
44  sort: Option<Sort>,
45  user: Option<UserId>,
46}
47
48impl<Field, Sort, Value> JsonQueryBuilder<Field, Sort, Value>
49where
50  Field: QueryField,
51  Sort: SortQueryBy,
52  Value: Serialize,
53{
54  pub(in crate::http) fn new(send_request: RequestFn<Value>) -> Self {
55    Self {
56      compact_filters: false,
57      count: false,
58      fields: None,
59      filters: JsonQueryFilter::default(),
60      normalized_filters: false,
61      page: None,
62      results: None,
63      reverse: false,
64      send_request,
65      sort: None,
66      user: None,
67    }
68  }
69
70  #[must_use]
71  pub fn compact_filters(mut self) -> Self {
72    self.compact_filters = true;
73    self
74  }
75
76  #[must_use]
77  pub fn count(mut self) -> Self {
78    self.count = true;
79    self
80  }
81
82  #[must_use]
83  pub fn fields(mut self, fields: impl Into<FieldSet<Field>>) -> Self {
84    let fields: FieldSet<Field> = fields.into();
85    if let Some(set) = &mut self.fields {
86      set.inner.extend(fields.inner);
87    } else {
88      self.fields = Some(fields);
89    }
90
91    self
92  }
93
94  #[must_use]
95  pub fn filters(mut self, filter: JsonQueryFilter) -> Self {
96    self.filters = filter;
97    self
98  }
99
100  #[must_use]
101  pub fn normalized_filters(mut self) -> Self {
102    self.normalized_filters = true;
103    self
104  }
105
106  #[must_use]
107  pub fn page(mut self, page: u16) -> Self {
108    self.page = Some(page.try_into().unwrap_or_else(|_| {
109      // SAFETY: Safe as long as the value is not zero.
110      unsafe { NonZeroU16::new_unchecked(1) }
111    }));
112
113    self
114  }
115
116  #[must_use]
117  pub fn raw_fields<I>(mut self, fields: I) -> Self
118  where
119    I: IntoIterator<Item = String>,
120  {
121    let set = FieldSet::from_raw(fields);
122    if let Some(current) = &mut self.fields {
123      current.inner.extend(set.inner);
124    } else {
125      self.fields = Some(set);
126    }
127
128    self
129  }
130
131  #[must_use]
132  pub fn results(mut self, results: u8) -> Self {
133    self.results = Some(results.min(100));
134    self
135  }
136
137  #[must_use]
138  pub fn reverse(mut self) -> Self {
139    self.reverse = true;
140    self
141  }
142
143  #[must_use]
144  pub fn sort(mut self, sort: Sort) -> Self {
145    self.sort = Some(sort);
146    self
147  }
148
149  #[must_use]
150  pub fn user(mut self, user: impl Into<UserId>) -> Self {
151    self.user = Some(user.into());
152    self
153  }
154
155  pub async fn send(self) -> Result<Value> {
156    let query = JsonQuery {
157      compact_filters: self.compact_filters,
158      count: self.count,
159      fields: self.fields.map(FieldSet::join),
160      filters: self.filters.into_inner(),
161      normalized_filters: self.normalized_filters,
162      page: self.page,
163      results: self.results,
164      reverse: self.reverse,
165      sort: self.sort.map(|s| s.to_string()),
166      user: self.user,
167    };
168
169    (self.send_request)(query).await
170  }
171}
172
173#[derive(Clone, Debug, Deserialize, Serialize)]
174pub struct JsonQueryFilter(JsonValue);
175
176impl JsonQueryFilter {
177  pub fn new(value: JsonValue) -> Self {
178    Self(value)
179  }
180
181  pub fn clear(&mut self) {
182    self.0 = JsonValue::Null;
183  }
184
185  pub fn into_inner(self) -> JsonValue {
186    self.0
187  }
188}
189
190impl Default for JsonQueryFilter {
191  fn default() -> Self {
192    Self(JsonValue::Null)
193  }
194}
195
196impl From<JsonValue> for JsonQueryFilter {
197  fn from(value: JsonValue) -> Self {
198    Self(value)
199  }
200}
201
202impl TryFrom<&str> for JsonQueryFilter {
203  type Error = crate::error::Error;
204
205  fn try_from(value: &str) -> Result<Self> {
206    serde_json::from_str(value)
207      .map(Self)
208      .map_err(Into::into)
209  }
210}
211
212impl TryFrom<String> for JsonQueryFilter {
213  type Error = crate::error::Error;
214
215  fn try_from(value: String) -> Result<Self> {
216    Self::try_from(value.as_str())
217  }
218}
219
220impl TryFrom<&String> for JsonQueryFilter {
221  type Error = crate::error::Error;
222
223  fn try_from(value: &String) -> Result<Self> {
224    Self::try_from(value.as_str())
225  }
226}
227
228impl TryFrom<Cow<'_, str>> for JsonQueryFilter {
229  type Error = crate::error::Error;
230
231  fn try_from(value: Cow<'_, str>) -> Result<Self> {
232    Self::try_from(value.as_ref())
233  }
234}