1use serde_json::{Number, Value};
4use std::f64;
5use std::str::FromStr;
6
7use crate::error::Error;
8
9const NUMERICS: &'static [char] = &[
11 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.', '-', '+', 'e', 'E',
12];
13
14pub fn to_string(value: &Value) -> String {
19 match value {
20 Value::Object(_) => String::from("[object Object]"),
21 Value::Bool(val) => val.to_string(),
22 Value::Null => String::from("null"),
23 Value::Number(val) => val.to_string(),
24 Value::String(val) => String::from(val),
25 Value::Array(val) => val
26 .iter()
27 .map(|i| match i {
28 Value::Null => String::from(""),
29 _ => to_string(i),
30 })
31 .collect::<Vec<String>>()
32 .join(","),
33 }
34}
35
36fn to_primitive_number(value: &Value) -> Option<f64> {
41 match value {
42 Value::Object(_) => None,
44 Value::Array(_) => None,
46 Value::Bool(val) => {
47 if *val {
48 Some(1.0)
49 } else {
50 Some(0.0)
51 }
52 }
53 Value::Null => Some(0.0),
54 Value::Number(val) => val.as_f64(),
55 Value::String(_) => None, }
57}
58
59pub fn str_to_number<S: AsRef<str>>(string: S) -> Option<f64> {
60 let s = string.as_ref();
61 if s == "" {
62 Some(0.0)
63 } else {
64 f64::from_str(s).ok()
65 }
66}
67
68enum Primitive {
69 String(String),
70 Number(f64),
71}
72
73#[allow(dead_code)]
74enum PrimitiveHint {
75 String,
76 Number,
77 Default,
78}
79
80fn to_primitive(value: &Value, hint: PrimitiveHint) -> Primitive {
81 match hint {
82 PrimitiveHint::String => Primitive::String(to_string(value)),
83 _ => to_primitive_number(value)
84 .map(Primitive::Number)
85 .unwrap_or(Primitive::String(to_string(value))),
86 }
87}
88
89pub fn to_number(value: &Value) -> Option<f64> {
94 match to_primitive(value, PrimitiveHint::Number) {
95 Primitive::Number(num) => Some(num),
96 Primitive::String(string) => str_to_number(string),
97 }
98}
99
100pub fn abstract_eq(first: &Value, second: &Value) -> bool {
178 match (first, second) {
180 (Value::Null, Value::Null) => true,
185 (Value::Number(x), Value::Number(y)) => {
187 x.as_f64()
193 .map(|x_val| y.as_f64().map(|y_val| x_val == y_val).unwrap_or(false))
194 .unwrap_or(false)
195 }
203 (Value::String(x), Value::String(y)) => x == y,
207 (Value::Bool(x), Value::Bool(y)) => x == y,
210 (Value::Number(x), Value::String(y)) => {
219 let y_res = str_to_number(y);
221 y_res
222 .map(|y_number| {
223 x.as_f64()
224 .map(|x_number| x_number == y_number)
225 .unwrap_or(false)
226 })
227 .unwrap_or(false)
228 }
229 (Value::String(x), Value::Number(y)) => {
232 let x_res = str_to_number(x);
233 x_res
234 .map(|x_number| {
235 y.as_f64()
236 .map(|y_number| x_number == y_number)
237 .unwrap_or(false)
238 })
239 .unwrap_or(false)
240 }
241 (Value::Bool(x), _) => match x {
243 true => Number::from_f64(1 as f64)
244 .map(|num| {
245 let value = Value::Number(num);
246 abstract_eq(&value, second)
247 })
248 .unwrap_or(false),
249 false => Number::from_f64(0 as f64)
250 .map(|num| {
251 let value = Value::Number(num);
252 abstract_eq(&value, second)
253 })
254 .unwrap_or(false),
255 },
256 (_, Value::Bool(y)) => match y {
258 true => Number::from_f64(1 as f64)
259 .map(|num| {
260 let value = Value::Number(num);
261 abstract_eq(first, &value)
262 })
263 .unwrap_or(false),
264 false => Number::from_f64(0 as f64)
265 .map(|num| {
266 let value = Value::Number(num);
267 abstract_eq(first, &value)
268 })
269 .unwrap_or(false),
270 },
271 (Value::String(_), Value::Array(_)) | (Value::Number(_), Value::Array(_)) => {
279 abstract_eq(first, &Value::String(to_string(second)))
280 }
281 (Value::String(_), Value::Object(_)) | (Value::Number(_), Value::Object(_)) => {
282 abstract_eq(first, &Value::String(to_string(second)))
283 }
284 (Value::Object(_), Value::String(_)) | (Value::Object(_), Value::Number(_)) => {
287 abstract_eq(&Value::String(to_string(first)), second)
288 }
289 (Value::Array(_), Value::String(_)) | (Value::Array(_), Value::Number(_)) => {
290 abstract_eq(&Value::String(to_string(first)), second)
291 }
292 _ => false,
293 }
294}
295
296pub fn strict_eq(first: &Value, second: &Value) -> bool {
326 if std::ptr::eq(first, second) {
327 return true;
328 };
329 match (first, second) {
330 (Value::Null, Value::Null) => true,
331 (Value::Bool(x), Value::Bool(y)) => x == y,
332 (Value::Number(x), Value::Number(y)) => x
333 .as_f64()
334 .and_then(|x_val| y.as_f64().map(|y_val| x_val == y_val))
335 .unwrap_or(false),
336 (Value::String(x), Value::String(y)) => x == y,
337 _ => false,
338 }
339}
340
341pub fn strict_ne(first: &Value, second: &Value) -> bool {
342 !strict_eq(first, second)
343}
344
345pub fn abstract_lt(first: &Value, second: &Value) -> bool {
359 match (
360 to_primitive(first, PrimitiveHint::Number),
361 to_primitive(second, PrimitiveHint::Number),
362 ) {
363 (Primitive::String(f), Primitive::String(s)) => f < s,
364 (Primitive::Number(f), Primitive::Number(s)) => f < s,
365 (Primitive::String(f), Primitive::Number(s)) => {
366 if let Some(f) = str_to_number(f) {
367 f < s
368 } else {
369 false
370 }
371 }
372 (Primitive::Number(f), Primitive::String(s)) => {
373 if let Some(s) = str_to_number(s) {
374 f < s
375 } else {
376 false
377 }
378 }
379 }
380}
381
382pub fn abstract_gt(first: &Value, second: &Value) -> bool {
394 match (
395 to_primitive(first, PrimitiveHint::Number),
396 to_primitive(second, PrimitiveHint::Number),
397 ) {
398 (Primitive::String(f), Primitive::String(s)) => f > s,
399 (Primitive::Number(f), Primitive::Number(s)) => f > s,
400 (Primitive::String(f), Primitive::Number(s)) => {
401 if let Some(f) = str_to_number(f) {
402 f > s
403 } else {
404 false
405 }
406 }
407 (Primitive::Number(f), Primitive::String(s)) => {
408 if let Some(s) = str_to_number(s) {
409 f > s
410 } else {
411 false
412 }
413 }
414 }
415}
416
417pub fn abstract_ne(first: &Value, second: &Value) -> bool {
419 !abstract_eq(first, second)
420}
421
422pub fn abstract_lte(first: &Value, second: &Value) -> bool {
424 abstract_lt(first, second) || abstract_eq(first, second)
425}
426
427pub fn abstract_gte(first: &Value, second: &Value) -> bool {
429 abstract_gt(first, second) || abstract_eq(first, second)
430}
431
432pub fn abstract_max(items: &Vec<&Value>) -> Result<f64, Error> {
434 items
435 .into_iter()
436 .map(|v| {
437 to_number(v).ok_or_else(|| Error::InvalidArgument {
438 value: (*v).clone(),
439 operation: "max".into(),
440 reason: "Could not convert value to number".into(),
441 })
442 })
443 .fold(Ok(f64::NEG_INFINITY), |acc, cur| {
444 let max = acc?;
445 match cur {
446 Ok(num) => {
447 if num > max {
448 Ok(num)
449 } else {
450 Ok(max)
451 }
452 }
453 _ => cur,
454 }
455 })
456}
457
458pub fn abstract_min(items: &Vec<&Value>) -> Result<f64, Error> {
460 items
461 .into_iter()
462 .map(|v| {
463 to_number(v).ok_or_else(|| Error::InvalidArgument {
464 value: (*v).clone(),
465 operation: "max".into(),
466 reason: "Could not convert value to number".into(),
467 })
468 })
469 .fold(Ok(f64::INFINITY), |acc, cur| {
470 let min = acc?;
471 match cur {
472 Ok(num) => {
473 if num < min {
474 Ok(num)
475 } else {
476 Ok(min)
477 }
478 }
479 _ => cur,
480 }
481 })
482}
483
484pub fn abstract_plus(first: &Value, second: &Value) -> Value {
486 let first_num = to_primitive_number(first);
487 let second_num = to_primitive_number(second);
488
489 match (first_num, second_num) {
490 (Some(f), Some(s)) => {
491 return Value::Number(Number::from_f64(f + s).unwrap());
492 }
493 _ => {}
494 };
495
496 let first_string = to_string(first);
497 let second_string = to_string(second);
498
499 Value::String(first_string.chars().chain(second_string.chars()).collect())
500}
501
502pub fn parse_float_add(vals: &Vec<&Value>) -> Result<f64, Error> {
519 vals.into_iter()
520 .map(|&v| {
521 parse_float(v).ok_or_else(|| Error::InvalidArgument {
522 value: v.clone(),
523 operation: "+".into(),
524 reason: "Argument could not be converted to a float".into(),
525 })
526 })
527 .fold(Ok(0.0), |acc, cur| {
528 let total = acc?;
529 match cur {
530 Ok(num) => Ok(total + num),
531 _ => cur,
532 }
533 })
534}
535
536pub fn parse_float_mul(vals: &Vec<&Value>) -> Result<f64, Error> {
542 vals.into_iter()
543 .map(|&v| {
544 parse_float(v).ok_or_else(|| Error::InvalidArgument {
545 value: v.clone(),
546 operation: "*".into(),
547 reason: "Argument could not be converted to a float".into(),
548 })
549 })
550 .fold(Ok(1.0), |acc, cur| {
551 let total = acc?;
552 match cur {
553 Ok(num) => Ok(total * num),
554 _ => cur,
555 }
556 })
557}
558
559pub fn abstract_minus(first: &Value, second: &Value) -> Result<f64, Error> {
561 let first_num = to_number(first);
562 let second_num = to_number(second);
563
564 if let None = first_num {
565 return Err(Error::InvalidArgument {
566 value: first.clone(),
567 operation: "-".into(),
568 reason: "Could not convert value to number.".into(),
569 });
570 }
571 if let None = second_num {
572 return Err(Error::InvalidArgument {
573 value: second.clone(),
574 operation: "-".into(),
575 reason: "Could not convert value to number.".into(),
576 });
577 }
578
579 Ok(first_num.unwrap() - second_num.unwrap())
580}
581
582pub fn abstract_div(first: &Value, second: &Value) -> Result<f64, Error> {
584 let first_num = to_number(first);
585 let second_num = to_number(second);
586
587 if let None = first_num {
588 return Err(Error::InvalidArgument {
589 value: first.clone(),
590 operation: "/".into(),
591 reason: "Could not convert value to number.".into(),
592 });
593 }
594 if let None = second_num {
595 return Err(Error::InvalidArgument {
596 value: second.clone(),
597 operation: "/".into(),
598 reason: "Could not convert value to number.".into(),
599 });
600 }
601
602 Ok(first_num.unwrap() / second_num.unwrap())
603}
604
605pub fn abstract_mod(first: &Value, second: &Value) -> Result<f64, Error> {
607 let first_num = to_number(first);
608 let second_num = to_number(second);
609
610 if let None = first_num {
611 return Err(Error::InvalidArgument {
612 value: first.clone(),
613 operation: "%".into(),
614 reason: "Could not convert value to number.".into(),
615 });
616 }
617 if let None = second_num {
618 return Err(Error::InvalidArgument {
619 value: second.clone(),
620 operation: "%".into(),
621 reason: "Could not convert value to number.".into(),
622 });
623 }
624
625 Ok(first_num.unwrap() % second_num.unwrap())
626}
627
628pub fn to_negative(val: &Value) -> Result<f64, Error> {
630 to_number(val)
631 .map(|v| -1.0 * v)
632 .ok_or_else(|| Error::InvalidArgument {
633 value: val.clone(),
634 operation: "to_negative".into(),
635 reason: "Could not convert value to a number".into(),
636 })
637}
638
639fn parse_float_string(val: &String) -> Option<f64> {
647 let (mut leading_numerics, _, _) = val.trim().chars().fold(
648 (Vec::new(), false, false),
649 |(mut acc, broke, saw_decimal), c| {
650 if broke {
651 (acc, broke, saw_decimal)
653 } else if NUMERICS.contains(&c) {
654 let is_decimal = c == '.';
655 if saw_decimal && is_decimal {
656 (acc, true, is_decimal)
658 } else {
659 acc.push(c);
661 (acc, broke, saw_decimal || is_decimal)
662 }
663 } else {
664 (acc, true, saw_decimal)
666 }
667 },
668 );
669 if leading_numerics.len() == 0 {
671 return None;
672 };
673 if let Some('e') | Some('E') = leading_numerics.last() {
674 leading_numerics.pop();
678 }
679
680 leading_numerics
682 .iter()
683 .collect::<String>()
684 .parse::<f64>()
685 .ok()
686}
687
688pub fn parse_float(val: &Value) -> Option<f64> {
693 match val {
694 Value::Number(num) => num.as_f64(),
695 Value::String(string) => parse_float_string(string),
696 _ => parse_float(&Value::String(to_string(&val))),
697 }
698}
699
700#[cfg(test)]
705mod abstract_operations {
706
707 use super::*;
708 use serde_json::json;
709
710 fn equal_values() -> Vec<(Value, Value)> {
711 vec![
712 (json!(null), json!(null)),
713 (json!(1), json!(1)),
714 (json!(1), json!(1.0)),
715 (json!(1.0), json!(1)),
716 (json!(0), json!(-0)),
717 (json!(-0), json!(0)),
718 (json!("foo"), json!("foo")),
719 (json!(""), json!("")),
720 (json!(true), json!(true)),
721 (json!(false), json!(false)),
722 (json!(1), json!("1")),
723 (json!(1), json!("1.0")),
724 (json!(1.0), json!("1.0")),
725 (json!(1.0), json!("1")),
726 (json!(0), json!("")),
727 (json!(0), json!("0")),
728 (json!(0), json!("-0")),
729 (json!(0), json!("+0")),
730 (json!(-1), json!("-1")),
731 (json!(-1.0), json!("-1")),
732 (json!(true), json!(1)),
733 (json!(true), json!("1")),
734 (json!(true), json!("1.0")),
735 (json!(true), json!([1])),
736 (json!(true), json!(["1"])),
737 (json!(false), json!(0)),
738 (json!(false), json!([])),
739 (json!(false), json!([0])),
740 (json!(false), json!("")),
741 (json!(false), json!("0")),
742 (json!("[object Object]"), json!({})),
743 (json!("[object Object]"), json!({"a": "a"})),
744 (json!(""), json!([])),
745 (json!(""), json!([null])),
746 (json!(","), json!([null, null])),
747 (json!("1,2"), json!([1, 2])),
748 (json!("a,b"), json!(["a", "b"])),
749 (json!(0), json!([])),
750 (json!(false), json!([])),
751 (json!(true), json!([1])),
752 (json!([]), json!("")),
753 (json!([null]), json!("")),
754 (json!([null, null]), json!(",")),
755 (json!([1, 2]), json!("1,2")),
756 (json!(["a", "b"]), json!("a,b")),
757 (json!([]), json!(0)),
758 (json!([0]), json!(0)),
759 (json!([]), json!(false)),
760 (json!([0]), json!(false)),
761 (json!([1]), json!(true)),
762 ]
763 }
764
765 fn lt_values() -> Vec<(Value, Value)> {
766 vec![
767 (json!(-1), json!(0)),
768 (json!("-1"), json!(0)),
769 (json!(0), json!(1)),
770 (json!(0), json!("1")),
771 (json!("foo"), json!("foos")),
772 (json!(""), json!("a")),
773 (json!(""), json!([1])),
774 (json!(""), json!([1, 2])),
775 (json!(""), json!("1")),
776 (json!(""), json!({})),
777 (json!(""), json!({"a": 1})),
778 (json!(false), json!(true)),
779 (json!(false), json!(1)),
780 (json!(false), json!("1")),
781 (json!(false), json!([1])),
782 (json!(null), json!(1)),
783 (json!(null), json!(true)),
784 (json!(null), json!("1")),
785 (json!([]), json!([1])),
786 (json!([]), json!([1, 2])),
787 (json!(0), json!([1])),
788 (json!("0"), json!({})),
789 (json!("0"), json!({"a": 1})),
790 (json!("0"), json!([1, 2])),
791 ]
792 }
793
794 fn gt_values() -> Vec<(Value, Value)> {
795 vec![
796 (json!(0), json!(-1)),
797 (json!(0), json!("-1")),
798 (json!(1), json!(0)),
799 (json!("1"), json!(0)),
800 (json!("foos"), json!("foo")),
801 (json!("a"), json!("")),
802 (json!([1]), json!("")),
803 (json!("1"), json!("")),
804 (json!("1"), json!("0")),
805 (json!(true), json!(false)),
806 (json!(1), json!(false)),
807 (json!("1"), json!(false)),
808 (json!([1]), json!(false)),
809 (json!(1), json!(null)),
810 (json!(true), json!(null)),
811 (json!("1"), json!(null)),
812 (json!([1]), json!([])),
813 (json!([1, 2]), json!([])),
814 ]
815 }
816
817 fn ne_values() -> Vec<(Value, Value)> {
818 vec![
819 (json!([]), json!([])),
820 (json!([1]), json!([1])),
821 (json!([1, 1]), json!([1, 1])),
822 (json!({}), json!({})),
823 (json!({"a": 1}), json!({"a": 1})),
824 (json!([]), json!({})),
825 (json!(0), json!(1)),
826 (json!("a"), json!("b")),
827 (json!(true), json!(false)),
828 (json!(true), json!([0])),
829 (json!(1.0), json!(1.1)),
830 (json!(null), json!(0)),
831 (json!(null), json!("")),
832 (json!(null), json!(false)),
833 (json!(null), json!(true)),
834 ]
835 }
836
837 fn not_gt_not_lt_not_eq() -> Vec<(Value, Value)> {
839 vec![
840 (json!(null), json!("")),
841 (json!(null), json!("a")),
842 (json!(0), json!("a")),
843 (json!(0), json!([1, 2])),
844 (json!([]), json!([])),
845 (json!([1]), json!([1])),
846 (json!([1, 2]), json!([1, 2])),
847 (json!({}), json!({})),
848 (json!(false), json!({})),
849 (json!(true), json!({})),
850 (json!(false), json!([1, 2])),
851 (json!(true), json!([1, 2])),
852 ]
853 }
854
855 fn plus_cases() -> Vec<(Value, Value, Value)> {
856 vec![
857 (json!(1), json!(1), json!(2.0)),
858 (json!(1), json!(true), json!(2.0)),
859 (json!(true), json!(true), json!(2.0)),
860 (json!(1), json!(false), json!(1.0)),
861 (json!(false), json!(false), json!(0.0)),
862 (json!(1), json!(null), json!(1.0)),
863 (json!(null), json!(null), json!(0.0)),
864 (json!(1), json!("1"), json!("11")),
865 (json!(1), json!([1]), json!("11")),
866 (json!(1), json!([1, 2]), json!("11,2")),
867 (json!(1), json!([1, null, 3]), json!("11,,3")),
868 (json!(1), json!({}), json!("1[object Object]")),
869 ]
870 }
871
872 #[test]
873 fn test_to_string_obj() {
874 assert_eq!(&to_string(&json!({})), "[object Object]");
875 assert_eq!(&to_string(&json!({"a": "b"})), "[object Object]");
876 }
877
878 #[test]
879 fn test_to_string_array() {
880 assert_eq!(&to_string(&json!([])), "");
881 assert_eq!(&to_string(&json!([1, 2, 3])), "1,2,3");
882 assert_eq!(&to_string(&json!([1, [2, 3], 4])), "1,2,3,4");
883 assert_eq!(&to_string(&json!([1, {}, 2])), "1,[object Object],2");
884 assert_eq!(&to_string(&json!(["a", "b"])), "a,b");
885 assert_eq!(&to_string(&json!([null])), "");
886 assert_eq!(&to_string(&json!([null, 1, 2, null])), ",1,2,");
887 assert_eq!(&to_string(&json!([true, false])), "true,false");
888 }
889
890 #[test]
891 fn test_to_string_null() {
892 assert_eq!(&to_string(&json!(null)), "null");
893 }
894
895 #[test]
896 fn test_to_string_bool() {
897 assert_eq!(&to_string(&json!(true)), "true");
898 assert_eq!(&to_string(&json!(false)), "false");
899 }
900
901 #[test]
902 fn test_to_string_number() {
903 assert_eq!(&to_string(&json!(1.0)), "1.0");
904 assert_eq!(&to_string(&json!(1)), "1");
905 }
906
907 #[test]
908 fn test_abstract_eq() {
909 equal_values().iter().for_each(|(first, second)| {
910 println!("{:?}-{:?}", &first, &second);
911 assert!(abstract_eq(&first, &second), true);
912 })
913 }
914
915 #[test]
916 fn test_abstract_ne() {
917 ne_values().iter().for_each(|(first, second)| {
918 println!("{:?}-{:?}", &first, &second);
919 assert_eq!(abstract_ne(&first, &second), true);
920 })
921 }
922
923 #[test]
924 fn test_abstract_lt() {
925 lt_values().iter().for_each(|(first, second)| {
926 println!("{:?}-{:?}", &first, &second);
927 assert_eq!(abstract_lt(&first, &second), true);
928 })
929 }
930
931 #[test]
932 fn test_abstract_gt() {
933 gt_values().iter().for_each(|(first, second)| {
934 println!("{:?}-{:?}", &first, &second);
935 assert_eq!(abstract_gt(&first, &second), true);
936 })
937 }
938
939 #[test]
940 fn test_eq_values_are_not_lt() {
941 equal_values().iter().for_each(|(first, second)| {
942 println!("{:?}-{:?}", &first, &second);
943 assert_eq!(abstract_lt(&first, &second), false);
944 })
945 }
946
947 #[test]
948 fn test_eq_values_are_not_gt() {
949 equal_values().iter().for_each(|(first, second)| {
950 println!("{:?}-{:?}", &first, &second);
951 assert_eq!(abstract_gt(&first, &second), false);
952 })
953 }
954
955 #[test]
956 fn test_eq_values_are_not_ne() {
957 equal_values().iter().for_each(|(first, second)| {
958 println!("{:?}-{:?}", &first, &second);
959 assert_eq!(abstract_ne(&first, &second), false);
960 })
961 }
962
963 #[test]
964 fn test_lt_values_are_not_eq() {
965 lt_values().iter().for_each(|(first, second)| {
966 println!("{:?}-{:?}", &first, &second);
967 assert_eq!(abstract_eq(&first, &second), false);
968 })
969 }
970
971 #[test]
972 fn test_lt_values_are_not_gt() {
973 lt_values().iter().for_each(|(first, second)| {
974 println!("{:?}-{:?}", &first, &second);
975 assert_eq!(abstract_gt(&first, &second), false);
976 })
977 }
978
979 #[test]
980 fn test_lt_values_are_ne() {
981 lt_values().iter().for_each(|(first, second)| {
982 println!("{:?}-{:?}", &first, &second);
983 assert_eq!(abstract_ne(&first, &second), true);
984 })
985 }
986
987 #[test]
988 fn test_gt_values_are_not_eq() {
989 gt_values().iter().for_each(|(first, second)| {
990 println!("{:?}-{:?}", &first, &second);
991 assert_eq!(abstract_eq(&first, &second), false);
992 })
993 }
994
995 #[test]
996 fn test_gt_values_are_not_lt() {
997 gt_values().iter().for_each(|(first, second)| {
998 println!("{:?}-{:?}", &first, &second);
999 assert_eq!(abstract_lt(&first, &second), false);
1000 })
1001 }
1002
1003 #[test]
1004 fn test_gt_values_are_ne() {
1005 gt_values().iter().for_each(|(first, second)| {
1006 println!("{:?}-{:?}", &first, &second);
1007 assert_eq!(abstract_ne(&first, &second), true);
1008 })
1009 }
1010
1011 #[test]
1012 fn test_incomparable() {
1013 not_gt_not_lt_not_eq().iter().for_each(|(first, second)| {
1014 println!("{:?}-{:?}", &first, &second);
1015 assert_eq!(abstract_lt(&first, &second), false);
1016 assert_eq!(abstract_gt(&first, &second), false);
1017 assert_eq!(abstract_eq(&first, &second), false);
1018 })
1019 }
1020
1021 #[test]
1024 fn test_lt_values_are_lte() {
1025 lt_values().iter().for_each(|(first, second)| {
1026 println!("{:?}-{:?}", &first, &second);
1027 assert_eq!(abstract_lte(&first, &second), true);
1028 })
1029 }
1030
1031 #[test]
1032 fn test_eq_values_are_lte() {
1033 equal_values().iter().for_each(|(first, second)| {
1034 println!("{:?}-{:?}", &first, &second);
1035 assert_eq!(abstract_lte(&first, &second), true);
1036 })
1037 }
1038
1039 #[test]
1040 fn test_gt_values_are_not_lte() {
1041 gt_values().iter().for_each(|(first, second)| {
1042 println!("{:?}-{:?}", &first, &second);
1043 assert_eq!(abstract_lte(&first, &second), false);
1044 })
1045 }
1046
1047 #[test]
1050 fn test_gt_values_are_gte() {
1051 gt_values().iter().for_each(|(first, second)| {
1052 println!("{:?}-{:?}", &first, &second);
1053 assert_eq!(abstract_gte(&first, &second), true);
1054 })
1055 }
1056
1057 #[test]
1058 fn test_eq_values_are_gte() {
1059 equal_values().iter().for_each(|(first, second)| {
1060 println!("{:?}-{:?}", &first, &second);
1061 assert_eq!(abstract_gte(&first, &second), true);
1062 })
1063 }
1064
1065 #[test]
1066 fn test_lt_values_are_not_gte() {
1067 lt_values().iter().for_each(|(first, second)| {
1068 println!("{:?}-{:?}", &first, &second);
1069 assert_eq!(abstract_gte(&first, &second), false);
1070 })
1071 }
1072
1073 #[test]
1074 fn test_abstract_plus() {
1075 plus_cases().iter().for_each(|(first, second, exp)| {
1076 println!("{:?}-{:?}", &first, &second);
1077 let result = abstract_plus(&first, &second);
1078 match result {
1079 Value::Number(ref i) => match exp {
1080 Value::Number(j) => assert_eq!(i, j),
1081 _ => assert!(false),
1082 },
1083 Value::String(ref i) => match exp {
1084 Value::String(j) => assert_eq!(i, j),
1085 _ => assert!(false),
1086 },
1087 _ => assert!(false),
1088 }
1089 })
1090 }
1091}
1092
1093#[cfg(test)]
1094mod test_abstract_max {
1095 use super::*;
1096 use serde_json::json;
1097
1098 fn max_cases() -> Vec<(Vec<Value>, Result<f64, ()>)> {
1099 vec![
1100 (vec![json!(1), json!(2), json!(3)], Ok(3.0)),
1101 (vec![json!("1"), json!(true), json!([1])], Ok(1.0)),
1102 (
1103 vec![json!(""), json!(null), json!([]), json!(false)],
1104 Ok(0.0),
1105 ),
1106 (vec![json!("foo")], Err(())),
1107 (vec![], Ok(f64::NEG_INFINITY)),
1108 ]
1109 }
1110
1111 #[test]
1112 fn test_abstract_max() {
1113 max_cases().into_iter().for_each(|(items, exp)| {
1114 println!("Max: {:?}", items);
1115 let res = abstract_max(&items.iter().collect());
1116 println!("Res: {:?}", res);
1117 match exp {
1118 Ok(exp) => assert_eq!(res.unwrap(), exp),
1119 _ => {
1120 res.unwrap_err();
1121 }
1122 };
1123 })
1124 }
1125}
1126
1127#[cfg(test)]
1128mod test_abstract_min {
1129 use super::*;
1130 use serde_json::json;
1131
1132 fn min_cases() -> Vec<(Vec<Value>, Result<f64, ()>)> {
1133 vec![
1134 (vec![json!(1), json!(2), json!(3)], Ok(1.0)),
1135 (vec![json!("1"), json!(true), json!([1])], Ok(1.0)),
1136 (
1137 vec![json!(""), json!(null), json!([]), json!(false)],
1138 Ok(0.0),
1139 ),
1140 (vec![json!("foo")], Err(())),
1141 (vec![], Ok(f64::INFINITY)),
1142 ]
1143 }
1144
1145 #[test]
1146 fn test_abstract_min() {
1147 min_cases().into_iter().for_each(|(items, exp)| {
1148 println!("Min: {:?}", items);
1149 let res = abstract_min(&items.iter().collect());
1150 println!("Res: {:?}", res);
1151 match exp {
1152 Ok(exp) => assert_eq!(res.unwrap(), exp),
1153 _ => {
1154 res.unwrap_err();
1155 }
1156 };
1157 })
1158 }
1159}
1160
1161#[cfg(test)]
1162mod test_abstract_minus {
1163 use super::*;
1164 use serde_json::json;
1165
1166 fn minus_cases() -> Vec<(Value, Value, Result<f64, ()>)> {
1167 vec![
1168 (json!(5), json!(2), Ok(3.0)),
1169 (json!(0), json!(2), Ok(-2.0)),
1170 (json!("5"), json!(2), Ok(3.0)),
1171 (json!(["5"]), json!(2), Ok(3.0)),
1172 (json!(["5"]), json!(true), Ok(4.0)),
1173 (json!("foo"), json!(true), Err(())),
1174 ]
1175 }
1176
1177 #[test]
1178 fn test_abstract_minus() {
1179 minus_cases().into_iter().for_each(|(first, second, exp)| {
1180 println!("Minus: {:?} - {:?}", first, second);
1181 let res = abstract_minus(&first, &second);
1182 println!("Res: {:?}", res);
1183 match exp {
1184 Ok(exp) => assert_eq!(res.unwrap(), exp),
1185 _ => {
1186 res.unwrap_err();
1187 }
1188 }
1189 })
1190 }
1191}
1192
1193#[cfg(test)]
1194mod test_strict {
1195
1196 use super::*;
1197 use serde_json::json;
1198
1199 fn eq_values() -> Vec<(Value, Value)> {
1200 vec![
1201 (json!(""), json!("")),
1202 (json!("foo"), json!("foo")),
1203 (json!(1), json!(1)),
1204 (json!(1), json!(1.0)),
1205 (json!(null), json!(null)),
1206 (json!(true), json!(true)),
1207 (json!(false), json!(false)),
1208 ]
1209 }
1210
1211 fn ne_values() -> Vec<(Value, Value)> {
1212 vec![
1213 (json!({}), json!({})),
1214 (json!({"a": "a"}), json!({"a": "a"})),
1215 (json!([]), json!([])),
1216 (json!("foo"), json!("noop")),
1217 (json!(1), json!(2)),
1218 (json!(0), json!([])),
1219 (json!(0), json!([0])),
1220 (json!(false), json!(null)),
1221 (json!(true), json!(false)),
1222 (json!(false), json!(true)),
1223 (json!(false), json!([])),
1224 (json!(false), json!("")),
1225 ]
1226 }
1227
1228 #[test]
1229 fn test_strict_eq() {
1230 eq_values().iter().for_each(|(first, second)| {
1231 println!("{:?}-{:?}", &first, &second);
1232 assert!(strict_eq(&first, &second));
1233 });
1234 ne_values().iter().for_each(|(first, second)| {
1235 println!("{:?}-{:?}", &first, &second);
1236 assert!(!strict_eq(&first, &second));
1237 });
1238 }
1239
1240 #[test]
1241 fn test_strict_eq_same_obj() {
1242 let obj = json!({});
1243 assert!(strict_eq(&obj, &obj))
1244 }
1245
1246 #[test]
1247 fn test_strict_ne() {
1248 ne_values().iter().for_each(|(first, second)| {
1249 println!("{:?}-{:?}", &first, &second);
1250 assert!(strict_ne(&first, &second));
1251 });
1252 eq_values().iter().for_each(|(first, second)| {
1253 println!("{:?}-{:?}", &first, &second);
1254 assert!(!strict_ne(&first, &second));
1255 });
1256 }
1257
1258 #[test]
1259 fn test_strict_ne_same_obj() {
1260 let obj = json!({});
1261 assert!(!strict_ne(&obj, &obj))
1262 }
1263}
1264
1265#[cfg(test)]
1266mod test_parse_float {
1267 use super::*;
1268 use serde_json::json;
1269
1270 fn cases() -> Vec<(Value, Option<f64>)> {
1271 vec![
1272 (json!(1), Some(1.0)),
1273 (json!(1.5), Some(1.5)),
1274 (json!(-1.5), Some(-1.5)),
1275 (json!("1"), Some(1.0)),
1276 (json!("1e2"), Some(100.0)),
1277 (json!("1E2"), Some(100.0)),
1278 (json!("1.1e2"), Some(110.0)),
1279 (json!("-1.1e2"), Some(-110.0)),
1280 (json!("1e-2"), Some(0.01)),
1281 (json!("1.0"), Some(1.0)),
1282 (json!("1.1"), Some(1.1)),
1283 (json!("1.1.1"), Some(1.1)),
1284 (json!("1234abc"), Some(1234.0)),
1285 (json!("1e"), Some(1.0)),
1286 (json!("1E"), Some(1.0)),
1287 (json!(false), None),
1288 (json!(true), None),
1289 (json!(null), None),
1290 (json!("+5"), Some(5.0)),
1291 (json!("-5"), Some(-5.0)),
1292 (json!([]), None),
1293 (json!([1]), Some(1.0)),
1294 (json!([1, 2]), Some(1.0)),
1297 (json!({}), None),
1298 ]
1299 }
1300
1301 #[test]
1302 fn test_parse_float() {
1303 cases()
1304 .into_iter()
1305 .for_each(|(input, exp)| assert_eq!(parse_float(&input), exp));
1306 }
1307}