1use std::collections::HashMap;
3
4use crate::context::{get_json_pointer, ValueRender};
5use crate::errors::{Error, Result};
6use crate::filter_utils::{get_sort_strategy_for_type, get_unique_strategy_for_type};
7use crate::utils::render_to_string;
8use serde_json::value::{to_value, Map, Value};
9
10pub fn nth(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
13 let arr = try_get_value!("nth", "value", Vec<Value>, value);
14
15 if arr.is_empty() {
16 return Ok(to_value("").unwrap());
17 }
18
19 let index = match args.get("n") {
20 Some(val) => try_get_value!("nth", "n", usize, val),
21 None => return Err(Error::msg("The `nth` filter has to have an `n` argument")),
22 };
23
24 Ok(arr.get(index).unwrap_or(&to_value("").unwrap()).to_owned())
25}
26
27pub fn first(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
30 let mut arr = try_get_value!("first", "value", Vec<Value>, value);
31
32 if arr.is_empty() {
33 Ok(to_value("").unwrap())
34 } else {
35 Ok(arr.swap_remove(0))
36 }
37}
38
39pub fn last(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
42 let mut arr = try_get_value!("last", "value", Vec<Value>, value);
43
44 Ok(arr.pop().unwrap_or_else(|| to_value("").unwrap()))
45}
46
47pub fn join(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
51 let arr = try_get_value!("join", "value", Vec<Value>, value);
52 let sep = match args.get("sep") {
53 Some(val) => try_get_value!("truncate", "sep", String, val),
54 None => String::new(),
55 };
56
57 let rendered = arr
59 .iter()
60 .map(|v| render_to_string(|| "joining array".to_string(), |w| v.render(w)))
61 .collect::<Result<Vec<_>>>()?;
62 to_value(&rendered.join(&sep)).map_err(Error::json)
63}
64
65pub fn sort(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
68 let arr = try_get_value!("sort", "value", Vec<Value>, value);
69 if arr.is_empty() {
70 return Ok(arr.into());
71 }
72
73 let attribute = match args.get("attribute") {
74 Some(val) => try_get_value!("sort", "attribute", String, val),
75 None => String::new(),
76 };
77 let ptr = match attribute.as_str() {
78 "" => "".to_string(),
79 s => get_json_pointer(s),
80 };
81
82 let first = arr[0].pointer(&ptr).ok_or_else(|| {
83 Error::msg(format!("attribute '{}' does not reference a field", attribute))
84 })?;
85
86 let mut strategy = get_sort_strategy_for_type(first)?;
87 for v in &arr {
88 let key = v.pointer(&ptr).ok_or_else(|| {
89 Error::msg(format!("attribute '{}' does not reference a field", attribute))
90 })?;
91 strategy.try_add_pair(v, key)?;
92 }
93 let sorted = strategy.sort();
94
95 Ok(sorted.into())
96}
97
98pub fn unique(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
102 let arr = try_get_value!("unique", "value", Vec<Value>, value);
103 if arr.is_empty() {
104 return Ok(arr.into());
105 }
106
107 let case_sensitive = match args.get("case_sensitive") {
108 Some(val) => try_get_value!("unique", "case_sensitive", bool, val),
109 None => false,
110 };
111
112 let attribute = match args.get("attribute") {
113 Some(val) => try_get_value!("unique", "attribute", String, val),
114 None => String::new(),
115 };
116 let ptr = match attribute.as_str() {
117 "" => "".to_string(),
118 s => get_json_pointer(s),
119 };
120
121 let first = arr[0].pointer(&ptr).ok_or_else(|| {
122 Error::msg(format!("attribute '{}' does not reference a field", attribute))
123 })?;
124
125 let disc = std::mem::discriminant(first);
126 let mut strategy = get_unique_strategy_for_type(first, case_sensitive)?;
127
128 let arr = arr
129 .into_iter()
130 .filter_map(|v| match v.pointer(&ptr) {
131 Some(key) => {
132 if disc == std::mem::discriminant(key) {
133 match strategy.insert(key) {
134 Ok(false) => None,
135 Ok(true) => Some(Ok(v)),
136 Err(e) => Some(Err(e)),
137 }
138 } else {
139 Some(Err(Error::msg("unique filter can't compare multiple types")))
140 }
141 }
142 None => None,
143 })
144 .collect::<Result<Vec<_>>>();
145
146 Ok(to_value(arr?).unwrap())
147}
148
149pub fn group_by(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
153 let arr = try_get_value!("group_by", "value", Vec<Value>, value);
154 if arr.is_empty() {
155 return Ok(Map::new().into());
156 }
157
158 let key = match args.get("attribute") {
159 Some(val) => try_get_value!("group_by", "attribute", String, val),
160 None => {
161 return Err(Error::msg("The `group_by` filter has to have an `attribute` argument"))
162 }
163 };
164
165 let mut grouped = Map::new();
166 let json_pointer = get_json_pointer(&key);
167
168 for val in arr {
169 if let Some(key_val) = val.pointer(&json_pointer).cloned() {
170 if key_val.is_null() {
171 continue;
172 }
173
174 let str_key = match key_val.as_str() {
175 Some(key) => key.to_owned(),
176 None => format!("{}", key_val),
177 };
178
179 if let Some(vals) = grouped.get_mut(&str_key) {
180 vals.as_array_mut().unwrap().push(val);
181 continue;
182 }
183
184 grouped.insert(str_key, Value::Array(vec![val]));
185 }
186 }
187
188 Ok(to_value(grouped).unwrap())
189}
190
191pub fn filter(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
195 let mut arr = try_get_value!("filter", "value", Vec<Value>, value);
196 if arr.is_empty() {
197 return Ok(arr.into());
198 }
199
200 let key = match args.get("attribute") {
201 Some(val) => try_get_value!("filter", "attribute", String, val),
202 None => return Err(Error::msg("The `filter` filter has to have an `attribute` argument")),
203 };
204 let value = args.get("value").unwrap_or(&Value::Null);
205
206 let json_pointer = get_json_pointer(&key);
207 arr = arr
208 .into_iter()
209 .filter(|v| {
210 let val = v.pointer(&json_pointer).unwrap_or(&Value::Null);
211 if value.is_null() {
212 !val.is_null()
213 } else {
214 val == value
215 }
216 })
217 .collect::<Vec<_>>();
218
219 Ok(to_value(arr).unwrap())
220}
221
222pub fn map(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
225 let arr = try_get_value!("map", "value", Vec<Value>, value);
226 if arr.is_empty() {
227 return Ok(arr.into());
228 }
229
230 let attribute = match args.get("attribute") {
231 Some(val) => try_get_value!("map", "attribute", String, val),
232 None => return Err(Error::msg("The `map` filter has to have an `attribute` argument")),
233 };
234
235 let json_pointer = get_json_pointer(&attribute);
236 let arr = arr
237 .into_iter()
238 .filter_map(|v| match v.pointer(&json_pointer) {
239 Some(val) if !val.is_null() => Some(val.clone()),
240 _ => None,
241 })
242 .collect::<Vec<_>>();
243
244 Ok(to_value(arr).unwrap())
245}
246
247#[inline]
248fn get_index(i: f64, array: &[Value]) -> usize {
249 if i >= 0.0 {
250 i as usize
251 } else {
252 (array.len() as f64 + i) as usize
253 }
254}
255
256pub fn slice(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
261 let arr = try_get_value!("slice", "value", Vec<Value>, value);
262 if arr.is_empty() {
263 return Ok(arr.into());
264 }
265
266 let start = match args.get("start") {
267 Some(val) => get_index(try_get_value!("slice", "start", f64, val), &arr),
268 None => 0,
269 };
270
271 let mut end = match args.get("end") {
272 Some(val) => get_index(try_get_value!("slice", "end", f64, val), &arr),
273 None => arr.len(),
274 };
275
276 if end > arr.len() {
277 end = arr.len();
278 }
279
280 if start >= end {
282 return Ok(Vec::<Value>::new().into());
283 }
284
285 Ok(arr[start..end].into())
286}
287
288pub fn concat(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
291 let mut arr = try_get_value!("concat", "value", Vec<Value>, value);
292
293 let value = match args.get("with") {
294 Some(val) => val,
295 None => return Err(Error::msg("The `concat` filter has to have a `with` argument")),
296 };
297
298 if value.is_array() {
299 match value {
300 Value::Array(vals) => {
301 for val in vals {
302 arr.push(val.clone());
303 }
304 }
305 _ => unreachable!("Got something other than an array??"),
306 }
307 } else {
308 arr.push(value.clone());
309 }
310
311 Ok(to_value(arr).unwrap())
312}
313
314#[cfg(test)]
315mod tests {
316 use super::*;
317 use serde_derive::{Deserialize, Serialize};
318 use serde_json::json;
319 use serde_json::value::{to_value, Value};
320 use std::collections::HashMap;
321
322 #[test]
323 fn test_nth() {
324 let mut args = HashMap::new();
325 args.insert("n".to_string(), to_value(1).unwrap());
326 let result = nth(&to_value(&vec![1, 2, 3, 4]).unwrap(), &args);
327 assert!(result.is_ok());
328 assert_eq!(result.unwrap(), to_value(&2).unwrap());
329 }
330
331 #[test]
332 fn test_nth_empty() {
333 let v: Vec<Value> = Vec::new();
334 let mut args = HashMap::new();
335 args.insert("n".to_string(), to_value(1).unwrap());
336 let result = nth(&to_value(&v).unwrap(), &args);
337 assert!(result.is_ok());
338 assert_eq!(result.unwrap(), to_value("").unwrap());
339 }
340
341 #[test]
342 fn test_first() {
343 let result = first(&to_value(&vec![1, 2, 3, 4]).unwrap(), &HashMap::new());
344 assert!(result.is_ok());
345 assert_eq!(result.unwrap(), to_value(&1).unwrap());
346 }
347
348 #[test]
349 fn test_first_empty() {
350 let v: Vec<Value> = Vec::new();
351
352 let result = first(&to_value(&v).unwrap(), &HashMap::new());
353 assert!(result.is_ok());
354 assert_eq!(result.ok().unwrap(), to_value("").unwrap());
355 }
356
357 #[test]
358 fn test_last() {
359 let result = last(&to_value(&vec!["Hello", "World"]).unwrap(), &HashMap::new());
360 assert!(result.is_ok());
361 assert_eq!(result.unwrap(), to_value("World").unwrap());
362 }
363
364 #[test]
365 fn test_last_empty() {
366 let v: Vec<Value> = Vec::new();
367
368 let result = last(&to_value(&v).unwrap(), &HashMap::new());
369 assert!(result.is_ok());
370 assert_eq!(result.ok().unwrap(), to_value("").unwrap());
371 }
372
373 #[test]
374 fn test_join_sep() {
375 let mut args = HashMap::new();
376 args.insert("sep".to_owned(), to_value(&"==").unwrap());
377
378 let result = join(&to_value(&vec!["Cats", "Dogs"]).unwrap(), &args);
379 assert!(result.is_ok());
380 assert_eq!(result.unwrap(), to_value(&"Cats==Dogs").unwrap());
381 }
382
383 #[test]
384 fn test_join_sep_omitted() {
385 let result = join(&to_value(&vec![1.2, 3.4]).unwrap(), &HashMap::new());
386 assert!(result.is_ok());
387 assert_eq!(result.unwrap(), to_value(&"1.23.4").unwrap());
388 }
389
390 #[test]
391 fn test_join_empty() {
392 let v: Vec<Value> = Vec::new();
393 let mut args = HashMap::new();
394 args.insert("sep".to_owned(), to_value(&"==").unwrap());
395
396 let result = join(&to_value(&v).unwrap(), &args);
397 assert!(result.is_ok());
398 assert_eq!(result.unwrap(), to_value(&"").unwrap());
399 }
400
401 #[test]
402 fn test_sort() {
403 let v = to_value(vec![3, -1, 2, 5, 4]).unwrap();
404 let args = HashMap::new();
405 let result = sort(&v, &args);
406 assert!(result.is_ok());
407 assert_eq!(result.unwrap(), to_value(vec![-1, 2, 3, 4, 5]).unwrap());
408 }
409
410 #[test]
411 fn test_sort_empty() {
412 let v = to_value(Vec::<f64>::new()).unwrap();
413 let args = HashMap::new();
414 let result = sort(&v, &args);
415 assert!(result.is_ok());
416 assert_eq!(result.unwrap(), to_value(Vec::<f64>::new()).unwrap());
417 }
418
419 #[derive(Deserialize, Eq, Hash, PartialEq, Serialize)]
420 struct Foo {
421 a: i32,
422 b: i32,
423 }
424
425 #[test]
426 fn test_sort_attribute() {
427 let v = to_value(vec![
428 Foo { a: 3, b: 5 },
429 Foo { a: 2, b: 8 },
430 Foo { a: 4, b: 7 },
431 Foo { a: 1, b: 6 },
432 ])
433 .unwrap();
434 let mut args = HashMap::new();
435 args.insert("attribute".to_string(), to_value(&"a").unwrap());
436
437 let result = sort(&v, &args);
438 assert!(result.is_ok());
439 assert_eq!(
440 result.unwrap(),
441 to_value(vec![
442 Foo { a: 1, b: 6 },
443 Foo { a: 2, b: 8 },
444 Foo { a: 3, b: 5 },
445 Foo { a: 4, b: 7 },
446 ])
447 .unwrap()
448 );
449 }
450
451 #[test]
452 fn test_sort_invalid_attribute() {
453 let v = to_value(vec![Foo { a: 3, b: 5 }]).unwrap();
454 let mut args = HashMap::new();
455 args.insert("attribute".to_string(), to_value(&"invalid_field").unwrap());
456
457 let result = sort(&v, &args);
458 assert!(result.is_err());
459 assert_eq!(
460 result.unwrap_err().to_string(),
461 "attribute 'invalid_field' does not reference a field"
462 );
463 }
464
465 #[test]
466 fn test_sort_multiple_types() {
467 let v = to_value(vec![Value::Number(12.into()), Value::Array(vec![])]).unwrap();
468 let args = HashMap::new();
469
470 let result = sort(&v, &args);
471 assert!(result.is_err());
472 assert_eq!(result.unwrap_err().to_string(), "expected number got []");
473 }
474
475 #[test]
476 fn test_sort_non_finite_numbers() {
477 let v = to_value(vec![
478 ::std::f64::NEG_INFINITY, ::std::f64::NAN,
480 ])
481 .unwrap();
482 let args = HashMap::new();
483
484 let result = sort(&v, &args);
485 assert!(result.is_err());
486 assert_eq!(result.unwrap_err().to_string(), "Null is not a sortable value");
487 }
488
489 #[derive(Deserialize, Eq, Hash, PartialEq, Serialize)]
490 struct TupleStruct(i32, i32);
491
492 #[test]
493 fn test_sort_tuple() {
494 let v = to_value(vec![
495 TupleStruct(0, 1),
496 TupleStruct(7, 0),
497 TupleStruct(-1, 12),
498 TupleStruct(18, 18),
499 ])
500 .unwrap();
501 let mut args = HashMap::new();
502 args.insert("attribute".to_string(), to_value("0").unwrap());
503
504 let result = sort(&v, &args);
505 assert!(result.is_ok());
506 assert_eq!(
507 result.unwrap(),
508 to_value(vec![
509 TupleStruct(-1, 12),
510 TupleStruct(0, 1),
511 TupleStruct(7, 0),
512 TupleStruct(18, 18),
513 ])
514 .unwrap()
515 );
516 }
517
518 #[test]
519 fn test_unique_numbers() {
520 let v = to_value(vec![3, -1, 3, 3, 5, 2, 5, 4]).unwrap();
521 let args = HashMap::new();
522 let result = unique(&v, &args);
523 assert!(result.is_ok());
524 assert_eq!(result.unwrap(), to_value(vec![3, -1, 5, 2, 4]).unwrap());
525 }
526
527 #[test]
528 fn test_unique_strings() {
529 let v = to_value(vec!["One", "Two", "Three", "one", "Two"]).unwrap();
530 let mut args = HashMap::new();
531 let result = unique(&v, &args);
532 assert!(result.is_ok());
533 assert_eq!(result.unwrap(), to_value(vec!["One", "Two", "Three"]).unwrap());
534
535 args.insert("case_sensitive".to_string(), to_value(true).unwrap());
536 let result = unique(&v, &args);
537 assert!(result.is_ok());
538 assert_eq!(result.unwrap(), to_value(vec!["One", "Two", "Three", "one"]).unwrap());
539 }
540
541 #[test]
542 fn test_unique_empty() {
543 let v = to_value(Vec::<f64>::new()).unwrap();
544 let args = HashMap::new();
545 let result = sort(&v, &args);
546 assert!(result.is_ok());
547 assert_eq!(result.unwrap(), to_value(Vec::<f64>::new()).unwrap());
548 }
549
550 #[test]
551 fn test_unique_attribute() {
552 let v = to_value(vec![
553 Foo { a: 1, b: 2 },
554 Foo { a: 3, b: 3 },
555 Foo { a: 1, b: 3 },
556 Foo { a: 0, b: 4 },
557 ])
558 .unwrap();
559 let mut args = HashMap::new();
560 args.insert("attribute".to_string(), to_value(&"a").unwrap());
561
562 let result = unique(&v, &args);
563 assert!(result.is_ok());
564 assert_eq!(
565 result.unwrap(),
566 to_value(vec![Foo { a: 1, b: 2 }, Foo { a: 3, b: 3 }, Foo { a: 0, b: 4 },]).unwrap()
567 );
568 }
569
570 #[test]
571 fn test_unique_invalid_attribute() {
572 let v = to_value(vec![Foo { a: 3, b: 5 }]).unwrap();
573 let mut args = HashMap::new();
574 args.insert("attribute".to_string(), to_value(&"invalid_field").unwrap());
575
576 let result = unique(&v, &args);
577 assert!(result.is_err());
578 assert_eq!(
579 result.unwrap_err().to_string(),
580 "attribute 'invalid_field' does not reference a field"
581 );
582 }
583
584 #[test]
585 fn test_unique_multiple_types() {
586 let v = to_value(vec![Value::Number(12.into()), Value::Array(vec![])]).unwrap();
587 let args = HashMap::new();
588
589 let result = unique(&v, &args);
590 assert!(result.is_err());
591 assert_eq!(result.unwrap_err().to_string(), "unique filter can't compare multiple types");
592 }
593
594 #[test]
595 fn test_unique_non_finite_numbers() {
596 let v = to_value(vec![
597 ::std::f64::NEG_INFINITY, ::std::f64::NAN,
599 ])
600 .unwrap();
601 let args = HashMap::new();
602
603 let result = unique(&v, &args);
604 assert!(result.is_err());
605 assert_eq!(result.unwrap_err().to_string(), "Null is not a unique value");
606 }
607
608 #[test]
609 fn test_unique_tuple() {
610 let v = to_value(vec![
611 TupleStruct(0, 1),
612 TupleStruct(-7, -1),
613 TupleStruct(-1, 1),
614 TupleStruct(18, 18),
615 ])
616 .unwrap();
617 let mut args = HashMap::new();
618 args.insert("attribute".to_string(), to_value("1").unwrap());
619
620 let result = unique(&v, &args);
621 assert!(result.is_ok());
622 assert_eq!(
623 result.unwrap(),
624 to_value(vec![TupleStruct(0, 1), TupleStruct(-7, -1), TupleStruct(18, 18),]).unwrap()
625 );
626 }
627
628 #[test]
629 fn test_slice() {
630 fn make_args(start: Option<usize>, end: Option<f64>) -> HashMap<String, Value> {
631 let mut args = HashMap::new();
632 if let Some(s) = start {
633 args.insert("start".to_string(), to_value(s).unwrap());
634 }
635 if let Some(e) = end {
636 args.insert("end".to_string(), to_value(e).unwrap());
637 }
638 args
639 }
640
641 let v = to_value(vec![1, 2, 3, 4, 5]).unwrap();
642
643 let inputs = vec![
644 (make_args(Some(1), None), vec![2, 3, 4, 5]),
645 (make_args(None, Some(2.0)), vec![1, 2]),
646 (make_args(Some(1), Some(2.0)), vec![2]),
647 (make_args(None, Some(-2.0)), vec![1, 2, 3]),
648 (make_args(None, None), vec![1, 2, 3, 4, 5]),
649 (make_args(Some(3), Some(1.0)), vec![]),
650 (make_args(Some(9), None), vec![]),
651 ];
652
653 for (args, expected) in inputs {
654 let res = slice(&v, &args);
655 assert!(res.is_ok());
656 assert_eq!(res.unwrap(), to_value(expected).unwrap());
657 }
658 }
659
660 #[test]
661 fn test_group_by() {
662 let input = json!([
663 {"id": 1, "year": 2015},
664 {"id": 2, "year": 2015},
665 {"id": 3, "year": 2016},
666 {"id": 4, "year": 2017},
667 {"id": 5, "year": 2017},
668 {"id": 6, "year": 2017},
669 {"id": 7, "year": 2018},
670 {"id": 8},
671 {"id": 9, "year": null},
672 ]);
673 let mut args = HashMap::new();
674 args.insert("attribute".to_string(), to_value("year").unwrap());
675
676 let expected = json!({
677 "2015": [{"id": 1, "year": 2015}, {"id": 2, "year": 2015}],
678 "2016": [{"id": 3, "year": 2016}],
679 "2017": [{"id": 4, "year": 2017}, {"id": 5, "year": 2017}, {"id": 6, "year": 2017}],
680 "2018": [{"id": 7, "year": 2018}],
681 });
682
683 let res = group_by(&input, &args);
684 assert!(res.is_ok());
685 assert_eq!(res.unwrap(), to_value(expected).unwrap());
686 }
687
688 #[test]
689 fn test_group_by_nested_key() {
690 let input = json!([
691 {"id": 1, "company": {"id": 1}},
692 {"id": 2, "company": {"id": 2}},
693 {"id": 3, "company": {"id": 3}},
694 {"id": 4, "company": {"id": 4}},
695 {"id": 5, "company": {"id": 4}},
696 {"id": 6, "company": {"id": 5}},
697 {"id": 7, "company": {"id": 5}},
698 {"id": 8},
699 {"id": 9, "company": null},
700 ]);
701 let mut args = HashMap::new();
702 args.insert("attribute".to_string(), to_value("company.id").unwrap());
703
704 let expected = json!({
705 "1": [{"id": 1, "company": {"id": 1}}],
706 "2": [{"id": 2, "company": {"id": 2}}],
707 "3": [{"id": 3, "company": {"id": 3}}],
708 "4": [{"id": 4, "company": {"id": 4}}, {"id": 5, "company": {"id": 4}}],
709 "5": [{"id": 6, "company": {"id": 5}}, {"id": 7, "company": {"id": 5}}],
710 });
711
712 let res = group_by(&input, &args);
713 assert!(res.is_ok());
714 assert_eq!(res.unwrap(), to_value(expected).unwrap());
715 }
716
717 #[test]
718 fn test_filter_empty() {
719 let res = filter(&json!([]), &HashMap::new());
720 assert!(res.is_ok());
721 assert_eq!(res.unwrap(), json!([]));
722 }
723
724 #[test]
725 fn test_filter() {
726 let input = json!([
727 {"id": 1, "year": 2015},
728 {"id": 2, "year": 2015},
729 {"id": 3, "year": 2016},
730 {"id": 4, "year": 2017},
731 {"id": 5, "year": 2017},
732 {"id": 6, "year": 2017},
733 {"id": 7, "year": 2018},
734 {"id": 8},
735 {"id": 9, "year": null},
736 ]);
737 let mut args = HashMap::new();
738 args.insert("attribute".to_string(), to_value("year").unwrap());
739 args.insert("value".to_string(), to_value(2015).unwrap());
740
741 let expected = json!([
742 {"id": 1, "year": 2015},
743 {"id": 2, "year": 2015},
744 ]);
745
746 let res = filter(&input, &args);
747 assert!(res.is_ok());
748 assert_eq!(res.unwrap(), to_value(expected).unwrap());
749 }
750
751 #[test]
752 fn test_filter_no_value() {
753 let input = json!([
754 {"id": 1, "year": 2015},
755 {"id": 2, "year": 2015},
756 {"id": 3, "year": 2016},
757 {"id": 4, "year": 2017},
758 {"id": 5, "year": 2017},
759 {"id": 6, "year": 2017},
760 {"id": 7, "year": 2018},
761 {"id": 8},
762 {"id": 9, "year": null},
763 ]);
764 let mut args = HashMap::new();
765 args.insert("attribute".to_string(), to_value("year").unwrap());
766
767 let expected = json!([
768 {"id": 1, "year": 2015},
769 {"id": 2, "year": 2015},
770 {"id": 3, "year": 2016},
771 {"id": 4, "year": 2017},
772 {"id": 5, "year": 2017},
773 {"id": 6, "year": 2017},
774 {"id": 7, "year": 2018},
775 ]);
776
777 let res = filter(&input, &args);
778 assert!(res.is_ok());
779 assert_eq!(res.unwrap(), to_value(expected).unwrap());
780 }
781
782 #[test]
783 fn test_map_empty() {
784 let res = map(&json!([]), &HashMap::new());
785 assert!(res.is_ok());
786 assert_eq!(res.unwrap(), json!([]));
787 }
788
789 #[test]
790 fn test_map() {
791 let input = json!([
792 {"id": 1, "year": 2015},
793 {"id": 2, "year": true},
794 {"id": 3, "year": 2016.5},
795 {"id": 4, "year": "2017"},
796 {"id": 5, "year": 2017},
797 {"id": 6, "year": 2017},
798 {"id": 7, "year": [1900, 1901]},
799 {"id": 8, "year": {"a": 2018, "b": 2019}},
800 {"id": 9},
801 {"id": 10, "year": null},
802 ]);
803 let mut args = HashMap::new();
804 args.insert("attribute".to_string(), to_value("year").unwrap());
805
806 let expected =
807 json!([2015, true, 2016.5, "2017", 2017, 2017, [1900, 1901], {"a": 2018, "b": 2019}]);
808
809 let res = map(&input, &args);
810 assert!(res.is_ok());
811 assert_eq!(res.unwrap(), to_value(expected).unwrap());
812 }
813
814 #[test]
815 fn test_concat_array() {
816 let input = json!([1, 2, 3,]);
817 let mut args = HashMap::new();
818 args.insert("with".to_string(), json!([3, 4]));
819 let expected = json!([1, 2, 3, 3, 4,]);
820
821 let res = concat(&input, &args);
822 assert!(res.is_ok());
823 assert_eq!(res.unwrap(), to_value(expected).unwrap());
824 }
825
826 #[test]
827 fn test_concat_single_value() {
828 let input = json!([1, 2, 3,]);
829 let mut args = HashMap::new();
830 args.insert("with".to_string(), json!(4));
831 let expected = json!([1, 2, 3, 4,]);
832
833 let res = concat(&input, &args);
834 assert!(res.is_ok());
835 assert_eq!(res.unwrap(), to_value(expected).unwrap());
836 }
837}