git.delta.rocks / jrsonnet / refs/commits / 5e5ab6bd1d3a

difftreelog

Merge pull request #56 from messense/member-count-builtin

Yaroslav Bolyukin2021-07-14parents: #07ae295 #859b044.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -128,6 +128,8 @@
 			("parseJson".into(), builtin_parse_json),
 			("asciiUpper".into(), builtin_ascii_upper),
 			("asciiLower".into(), builtin_ascii_lower),
+			("member".into(), builtin_member),
+			("count".into(), builtin_count),
 		].iter().cloned().collect()
 	};
 }
@@ -854,6 +856,46 @@
 	})
 }
 
+fn builtin_member(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+	parse_args!(context, "member", args, 2, [
+		0, arr: ty!((array | string));
+		1, x: ty!(any);
+	], {
+		match arr {
+			Val::Str(s) => {
+				let x = x.try_cast_str("x should be string")?;
+				Ok(Val::Bool(!x.is_empty() && s.contains(&*x)))
+			}
+			Val::Arr(a) => {
+				for item in a.iter() {
+					let item = item?;
+					if equals(&item, &x)? {
+						return Ok(Val::Bool(true));
+					}
+				}
+				Ok(Val::Bool(false))
+			}
+			_ => unreachable!(),
+		}
+	})
+}
+
+fn builtin_count(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+	parse_args!(context, "count", args, 2, [
+		0, arr: ty!(array) => Val::Arr;
+		1, x: ty!(any);
+	], {
+		let mut count = 0;
+		for item in arr.iter() {
+			let item = item?;
+			if equals(&item, &x)? {
+				count += 1;
+			}
+		}
+		Ok(Val::Num(count as f64))
+	})
+}
+
 pub fn call_builtin(
 	context: Context,
 	loc: Option<&ExprLocation>,
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -1051,4 +1051,21 @@
 		assert_eval!(r#"std.assertEqual(std.asciiUpper("aBc😀"), "ABC😀")"#);
 		assert_eval!(r#"std.assertEqual(std.asciiLower("aBc😀"), "abc😀")"#);
 	}
+
+	#[test]
+	fn test_member() {
+		assert_eval!(r#"!std.member("", "")"#);
+		assert_eval!(r#"std.member("abc", "a")"#);
+		assert_eval!(r#"!std.member("abc", "d")"#);
+		assert_eval!(r#"!std.member([], "")"#);
+		assert_eval!(r#"std.member(["a", "b", "c"], "a")"#);
+		assert_eval!(r#"!std.member(["a", "b", "c"], "d")"#);
+	}
+
+	#[test]
+	fn test_count() {
+		assert_eval!(r#"std.assertEqual(std.count([], ""), 0)"#);
+		assert_eval!(r#"std.assertEqual(std.count(["a", "b", "a"], "d"), 0)"#);
+		assert_eval!(r#"std.assertEqual(std.count(["a", "b", "a"], "a"), 2)"#);
+	}
 }
modifiedcrates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth
143143
144 slice:: $intrinsic(slice),144 slice:: $intrinsic(slice),
145145
146 member(arr, x)::146 member:: $intrinsic(member),
147 if std.isArray(arr) then
148 std.count(arr, x) > 0
149 else if std.isString(arr) then
150 std.length(std.findSubstr(x, arr)) > 0
151 else error 'std.member first argument must be an array or a string',
152147
153 count(arr, x):: std.length(std.filter(function(v) v == x, arr)),148 count:: $intrinsic(count),
154149
155 mod:: $intrinsic(mod),150 mod:: $intrinsic(mod),
156151