subgraph/utils/document/get_from_document/
mod.rs1use bson::{oid::ObjectId, Bson};
2use log::{debug, error, trace};
3
4use super::DocumentUtils;
5
6#[derive(Debug)]
7pub enum DocumentValue {
8 String(String),
9 StringArray(Vec<String>),
10 Int(i32),
11 IntArray(Vec<i32>),
12 Boolean(bool),
13 BooleanArray(Vec<bool>),
14 ObjectID(bson::oid::ObjectId),
15 ObjectIDArray(Vec<bson::oid::ObjectId>),
16 Document(bson::Document),
17 DocumentArray(Vec<bson::Document>),
18 UUID(uuid::Uuid),
19 UUIDArray(Vec<uuid::Uuid>),
20 DateTime(chrono::DateTime<chrono::Utc>),
21 DateTimeArray(Vec<chrono::DateTime<chrono::Utc>>),
22 Null,
23 None,
24}
25
26impl DocumentUtils {
27 pub fn get_document_string_scalar(
28 document: &bson::Document,
29 field_name: &str,
30 is_list: bool,
31 ) -> Result<DocumentValue, async_graphql::Error> {
32 debug!("Getting Document String Scalar: {}", field_name);
33
34 if document.get(field_name).is_none() {
35 return Ok(DocumentValue::None);
36 }
37
38 if document.get(field_name).unwrap().as_null().is_some() {
39 return Ok(DocumentValue::Null);
40 }
41
42 if is_list {
43 if let Some(Bson::Array(documents)) = document.get(field_name) {
44 let valid_strings = documents.iter().all(|value| value.as_str().is_some());
45
46 if !valid_strings {
47 error!("Not all values are strings for field {}", field_name);
48 return Err(async_graphql::Error::new(format!(
49 "Not all values are strings for field {}",
50 field_name
51 )));
52 }
53
54 let values = documents
55 .into_iter()
56 .map(|value| value.as_str().unwrap().to_string())
57 .collect::<Vec<String>>();
58 trace!("Document Value String Array: {:?}", values);
59 return Ok(DocumentValue::StringArray(values));
60 } else {
61 trace!("Document Value String Array: Empty Vec");
62 return Ok(DocumentValue::StringArray(vec![]));
63 }
64 }
65
66 let value = document.get_str(field_name).map_err(|err| {
67 error!("Value is not a string: {}", err);
68 async_graphql::Error::new(format!("Value is not a string: {}", err))
69 })?;
70
71 trace!("Found String Value: {:?}", value);
72 Ok(DocumentValue::String(value.to_string()))
73 }
74
75 pub fn get_document_int_scalar(
76 document: &bson::Document,
77 field_name: &str,
78 is_list: bool,
79 ) -> Result<DocumentValue, async_graphql::Error> {
80 debug!("Getting Document Int Scalar: {}", field_name);
81
82 if document.get(field_name).is_none() {
83 return Ok(DocumentValue::None);
84 }
85
86 if document.get(field_name).unwrap().as_null().is_some() {
87 return Ok(DocumentValue::Null);
88 }
89
90 if is_list {
91 if let Some(Bson::Array(documents)) = document.get(field_name) {
92 let valid = documents.iter().all(|value| {
94 let i32_value = value.as_i32();
95 if i32_value.is_none() {
96 let i64_value = value.as_f64();
97 if i64_value.is_some() {
98 return true;
99 } else {
100 return false;
101 }
102 }
103 return true;
104 });
105
106 if !valid {
107 error!("Not all values are ints for field {}", field_name);
108 return Err(async_graphql::Error::new(format!(
109 "Not all values are ints for field {}",
110 field_name
111 )));
112 }
113
114 let values = documents
115 .into_iter()
116 .map(|value| {
117 let i32_value = value.as_i32();
118 if i32_value.is_none() {
119 let i64_value = value.as_f64();
120 if i64_value.is_some() {
121 return i64_value.unwrap() as i32;
122 } else {
123 error!("Could not parse int value: {:?}", value);
125 return -1;
126 }
127 }
128 return i32_value.unwrap();
129 })
130 .collect::<Vec<i32>>();
131 trace!("Document Value Int Array: {:?}", values);
132 return Ok(DocumentValue::IntArray(values));
133 } else {
134 trace!("Document Value Int Array: Empty Vec");
135 return Ok(DocumentValue::IntArray(vec![]));
136 }
137 }
138
139 let value = document.get(field_name).unwrap();
140 let i32_value = value.as_i32();
141 if i32_value.is_none() {
142 let i64_value = value.as_i64();
143 if i64_value.is_some() {
144 return Ok(DocumentValue::Int(i64_value.unwrap() as i32));
145 } else {
146 error!("Could not parse int value: {:?}", value);
147 return Err(async_graphql::Error::new(format!(
148 "Could not parse int value: {:?}",
149 value
150 )));
151 }
152 }
153 trace!("Found Int Value: {:?}", value);
154 Ok(DocumentValue::Int(i32_value.unwrap()))
155 }
156
157 pub fn get_document_boolean_scalar(
158 document: &bson::Document,
159 field_name: &str,
160 is_list: bool,
161 ) -> Result<DocumentValue, async_graphql::Error> {
162 debug!("Getting Document Boolean Scalar: {}", field_name);
163
164 if document.get(field_name).is_none() {
165 return Ok(DocumentValue::None);
166 }
167
168 if document.get(field_name).unwrap().as_null().is_some() {
169 return Ok(DocumentValue::Null);
170 }
171
172 if is_list {
173 let valid_bools = document
174 .get_array(field_name)?
175 .into_iter()
176 .all(|value| value.as_bool().is_some());
177
178 if !valid_bools {
179 error!("Not all values are booleans for field {}", field_name);
180 return Err(async_graphql::Error::new(format!(
181 "Not all values are booleans for field {}",
182 field_name
183 )));
184 }
185
186 let values = document
187 .get_array(field_name)?
188 .into_iter()
189 .map(|value| value.as_bool().unwrap())
190 .collect::<Vec<bool>>();
191 trace!("Document Value Boolean Array: {:?}", values);
192 return Ok(DocumentValue::BooleanArray(values));
193 }
194
195 let value = document.get_bool(field_name).map_err(|err| {
196 error!("Value is not a boolean: {}", err);
197 async_graphql::Error::new(format!("Value is not a boolean: {}", err))
198 })?;
199 trace!("Found Boolean Value: {:?}", value);
200 Ok(DocumentValue::Boolean(value))
201 }
202
203 pub fn get_document_uuid_scalar(
204 document: &bson::Document,
205 field_name: &str,
206 is_list: bool,
207 ) -> Result<DocumentValue, async_graphql::Error> {
208 debug!("Getting Document UUID Scalar: {}", field_name);
209
210 if document.get(field_name).is_none() {
211 return Ok(DocumentValue::None);
212 }
213
214 if document.get(field_name).unwrap().as_null().is_some() {
215 return Ok(DocumentValue::Null);
216 }
217
218 if is_list {
219 if let Some(Bson::Array(documents)) = document.get(field_name) {
220 let valid_uuids = documents.iter().all(|value| {
221 let value = value.as_str().unwrap_or("");
222 let uuid = uuid::Uuid::parse_str(value);
223 if uuid.is_err() {
224 return false;
225 } else {
226 return true;
227 }
228 });
229
230 if !valid_uuids {
231 error!("Not all values are uuids for field {}", field_name);
232 return Err(async_graphql::Error::new(format!(
233 "Not all values are uuids for field {}",
234 field_name
235 )));
236 }
237
238 let values = documents
239 .into_iter()
240 .map(|value| {
241 let value = value.as_str().unwrap_or("");
242 let uuid = uuid::Uuid::parse_str(value);
243 if uuid.is_err() {
244 uuid::Uuid::nil()
245 } else {
246 uuid.unwrap()
247 }
248 })
249 .collect();
250 trace!("Document Value UUID Array: {:?}", values);
251 return Ok(DocumentValue::UUIDArray(values));
252 } else {
253 trace!("Document Value UUID Array: Empty Vec");
254 return Ok(DocumentValue::UUIDArray(vec![]));
255 }
256 }
257
258 let value = document.get_str(field_name).map_err(|err| {
259 error!("Value is not a uuid: {}", err);
260 async_graphql::Error::new(format!("Value is not a uuid: {}", err))
261 })?;
262
263 trace!("Document Value UUID: {:?}", value);
264 Ok(DocumentValue::UUID(uuid::Uuid::parse_str(value).unwrap()))
265 }
266
267 pub fn get_document_datetime_scalar(
268 document: &bson::Document,
269 field_name: &str,
270 is_list: bool,
271 ) -> Result<DocumentValue, async_graphql::Error> {
272 debug!("Getting Document DateTime Scalar: {}", field_name);
273
274 if document.get(field_name).is_none() {
275 return Ok(DocumentValue::None);
276 }
277
278 if document.get(field_name).unwrap().as_null().is_some() {
279 return Ok(DocumentValue::Null);
280 }
281
282 if is_list {
283 if let Some(Bson::Array(documents)) = document.get(field_name) {
284 let is_valid = documents.iter().all(|value| {
286 let value = value.as_datetime();
287 if value.is_none() {
288 return false;
289 }
290 true
291 });
292 if !is_valid {
293 error!("Not all values are valid dates for field {}", field_name);
294 return Err(async_graphql::Error::new("Invalid DateTime"));
295 }
296 let values = documents
297 .into_iter()
298 .map(|value| {
299 let value = value.as_datetime().unwrap();
300 value.to_chrono()
301 })
302 .collect();
303 trace!("Document Value DateTime Array: {:?}", values);
304 return Ok(DocumentValue::DateTimeArray(values));
305 } else {
306 trace!("Document Value DateTime Array: Empty Vec");
307 return Ok(DocumentValue::DateTimeArray(vec![]));
308 }
309 }
310
311 let value = document.get_datetime(field_name).map_err(|err| {
312 error!("Value is not a datetime: {}", err);
313 async_graphql::Error::new(format!("Value is not a datetime: {}", err))
314 })?;
315 trace!("Document Value DateTime: {:?}", value);
317 Ok(DocumentValue::DateTime(value.to_chrono()))
318 }
319
320 pub fn get_document_object_id_scalar(
321 document: &bson::Document,
322 field_name: &str,
323 is_list: bool,
324 ) -> Result<DocumentValue, async_graphql::Error> {
325 debug!("Getting Document ObjectID Scalar: {}", field_name);
326
327 if document.get(field_name).is_none() {
328 return Ok(DocumentValue::None);
329 }
330
331 if document.get(field_name).unwrap().as_null().is_some() {
332 return Ok(DocumentValue::Null);
333 }
334
335 if is_list {
336 if let Some(Bson::Array(documents)) = document.get(field_name) {
337 let valid_object_ids = documents.iter().all(|value| {
338 let value = value.as_object_id();
339 if value.is_none() {
340 return false;
341 }
342 true
343 });
344
345 if !valid_object_ids {
346 error!("Not all values are object ids for field {}", field_name);
347 return Err(async_graphql::Error::new(format!(
348 "Not all values are object ids for field {}",
349 field_name
350 )));
351 }
352
353 let value = documents
354 .into_iter()
355 .map(|value| value.as_object_id().unwrap())
356 .collect::<Vec<ObjectId>>();
357 trace!("Document Value ObjectID Array: {:?}", value);
358 return Ok(DocumentValue::ObjectIDArray(value));
359 } else {
360 trace!("Document Value ObjectID Array: Empty Vec");
361 return Ok(DocumentValue::ObjectIDArray(vec![]));
362 }
363 }
364 let value = document.get_object_id(field_name).map_err(|err| {
365 error!("Value is not an object id: {}", err);
366 async_graphql::Error::new(format!("Value is not an object id: {}", err))
367 })?;
368 trace!("Document Value ObjectID: {:?}", value);
369 Ok(DocumentValue::ObjectID(value))
370 }
371
372 pub fn get_document_object_scalar(
373 document: &bson::Document,
374 field_name: &str,
375 is_list: bool,
376 ) -> Result<DocumentValue, async_graphql::Error> {
377 debug!("Get Document Object Scalar");
378 trace!("Field Name: {}", field_name);
379
380 if document.get(field_name).is_none() {
381 return Ok(DocumentValue::None);
382 }
383
384 if document.get(field_name).unwrap().as_null().is_some() {
385 return Ok(DocumentValue::Null);
386 }
387
388 let value = document.get(field_name).unwrap();
389
390 if is_list {
391 if let Some(bson_array) = value.as_array() {
392 let valid_docs = bson_array.iter().all(|value| {
393 let value = value.as_document();
394 if value.is_none() {
395 return false;
396 }
397 true
398 });
399
400 if !valid_docs {
401 error!("Not all values are documents for field {}", field_name);
402 return Err(async_graphql::Error::new(format!(
403 "Not all values are documents for field {}",
404 field_name
405 )));
406 }
407
408 let values = bson_array
409 .into_iter()
410 .map(|value| value.as_document().unwrap().clone())
411 .collect::<Vec<bson::Document>>();
412 trace!("Document Value Object Array: {:?}", values);
413 return Ok(DocumentValue::DocumentArray(values));
414 } else {
415 trace!("Document Value Object Array: Empty Vec");
416 return Ok(DocumentValue::DocumentArray(vec![]));
417 }
418 } else {
419 trace!("Document Value Object: {:?}", value);
420 Ok(DocumentValue::Document(
421 value.as_document().unwrap().clone(),
422 ))
423 }
424 }
425
426 pub fn get_document_enum_scalar(
427 document: &bson::Document,
428 field_name: &str,
429 is_list: bool,
430 ) -> Result<DocumentValue, async_graphql::Error> {
431 debug!("Resolving Enum Scalar");
432
433 if document.get(field_name).is_none() {
434 trace!(
435 "Field `{}` not found, returning DocumentValue::None",
436 field_name
437 );
438 return Ok(DocumentValue::None);
439 }
440
441 if document.get(field_name).unwrap().as_null().is_some() {
442 trace!(
443 "Field `{}` is null, returning DocumentValue::Null",
444 field_name
445 );
446 return Ok(DocumentValue::Null);
447 }
448
449 if is_list {
450 if let Some(Bson::Array(documents)) = document.get(field_name) {
451 let valid_strings = documents.iter().all(|value| value.as_str().is_some());
452
453 if !valid_strings {
454 error!("Not all values are strings for field {}", field_name);
455 return Err(async_graphql::Error::new(format!(
456 "Not all values are strings for field {}",
457 field_name
458 )));
459 }
460
461 let values = documents
462 .into_iter()
463 .map(|value| value.as_str().unwrap().to_string())
464 .collect::<Vec<String>>();
465 trace!("Document Value String Array: {:?}", values);
466 return Ok(DocumentValue::StringArray(values));
467 } else {
468 trace!("Document Value String Array: Empty Vec");
469 return Ok(DocumentValue::StringArray(vec![]));
470 }
471 }
472
473 let value = document.get_str(field_name).map_err(|err| {
474 error!("Value is not a string: {}", err);
475 async_graphql::Error::new(format!("Value is not a string: {}", err))
476 })?;
477
478 trace!("Found String Value: {:?}", value);
479 Ok(DocumentValue::String(value.to_string()))
480 }
481}