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