git.delta.rocks / jrsonnet / refs/commits / 4ab075dbe65c

difftreelog

fix std function argument names

Yaroslav Bolyukin2023-08-10parent: #cfa49ab.patch.diff
in: master

6 files changed

modifiedcrates/jrsonnet-stdlib/src/arrays.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/arrays.rs
+++ b/crates/jrsonnet-stdlib/src/arrays.rs
@@ -255,9 +255,9 @@
 }
 
 #[builtin]
-pub fn builtin_remove_at(arr: ArrValue, index: usize) -> Result<ArrValue> {
-	let newArrLeft = arr.clone().slice(None, Some(index), None);
-	let newArrRight = arr.slice(Some(index + 1), None, None);
+pub fn builtin_remove_at(arr: ArrValue, at: usize) -> Result<ArrValue> {
+	let newArrLeft = arr.clone().slice(None, Some(at), None);
+	let newArrRight = arr.slice(Some(at + 1), None, None);
 
 	Ok(ArrValue::extended(
 		newArrLeft.unwrap_or(ArrValue::empty()),
modifiedcrates/jrsonnet-stdlib/src/hash.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/hash.rs
+++ b/crates/jrsonnet-stdlib/src/hash.rs
@@ -6,25 +6,25 @@
 }
 
 #[builtin]
-pub fn builtin_sha256(s: IStr) -> String {
+pub fn builtin_sha256(str: IStr) -> String {
 	use sha2::digest::Digest;
-	format!("{:x}", sha2::Sha256::digest(s.as_bytes()))
+	format!("{:x}", sha2::Sha256::digest(str.as_bytes()))
 }
 
 #[builtin]
-pub fn builtin_sha512(s: IStr) -> String {
+pub fn builtin_sha512(str: IStr) -> String {
 	use sha2::digest::Digest;
-	format!("{:x}", sha2::Sha512::digest(s.as_bytes()))
+	format!("{:x}", sha2::Sha512::digest(str.as_bytes()))
 }
 
 #[builtin]
-pub fn builtin_sha1(s: IStr) -> String {
+pub fn builtin_sha1(str: IStr) -> String {
 	use sha1::digest::Digest;
-	format!("{:x}", sha1::Sha1::digest(s.as_bytes()))
+	format!("{:x}", sha1::Sha1::digest(str.as_bytes()))
 }
 
 #[builtin]
-pub fn builtin_sha3(s: IStr) -> String {
+pub fn builtin_sha3(str: IStr) -> String {
 	use sha3::digest::Digest;
-	format!("{:x}", sha3::Sha3_512::digest(s.as_bytes()))
+	format!("{:x}", sha3::Sha3_512::digest(str.as_bytes()))
 }
modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/lib.rs
+++ b/crates/jrsonnet-stdlib/src/lib.rs
@@ -80,7 +80,7 @@
 		("any", builtin_any::INST),
 		("all", builtin_all::INST),
 		("member", builtin_member::INST),
-		("contains", builtin_member::INST),
+		("contains", builtin_contains::INST),
 		("count", builtin_count::INST),
 		("avg", builtin_avg::INST),
 		("removeAt", builtin_remove_at::INST),
modifiedcrates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/misc.rs
+++ b/crates/jrsonnet-stdlib/src/misc.rs
@@ -57,12 +57,12 @@
 	this: &builtin_trace,
 	loc: CallLocation,
 	str: Val,
-	rest: Thunk<Val>,
+	rest: Option<Thunk<Val>>,
 ) -> Result<Val> {
 	this.settings.borrow().trace_printer.print_trace(
 		loc,
-		match str {
-			Val::Str(s) => s.into_flat(),
+		match &str {
+			Val::Str(s) => s.clone().into_flat(),
 			Val::Func(f) => format!("{f:?}").into(),
 			v => v
 				.manifest(JsonFormat::std_to_json(
@@ -75,7 +75,11 @@
 				.into(),
 		},
 	);
-	rest.evaluate()
+	if let Some(rest) = rest {
+		rest.evaluate()
+	} else {
+		Ok(str)
+	}
 }
 
 #[allow(clippy::comparison_chain)]
modifiedcrates/jrsonnet-stdlib/src/strings.rsdiffbeforeafterboth
before · crates/jrsonnet-stdlib/src/strings.rs
1use jrsonnet_evaluator::{2	error::{ErrorKind::*, Result},3	function::builtin,4	throw,5	typed::{Either2, M1},6	val::{ArrValue, StrValue},7	Either, IStr, Val,8};910#[builtin]11pub const fn builtin_codepoint(str: char) -> u32 {12	str as u3213}1415#[builtin]16pub fn builtin_substr(str: IStr, from: usize, len: usize) -> String {17	str.chars().skip(from).take(len).collect()18}1920#[builtin]21pub fn builtin_char(n: u32) -> Result<char> {22	Ok(std::char::from_u32(n).ok_or_else(|| InvalidUnicodeCodepointGot(n))?)23}2425#[builtin]26pub fn builtin_str_replace(str: String, from: IStr, to: IStr) -> String {27	str.replace(&from as &str, &to as &str)28}2930#[builtin]31pub fn builtin_is_empty(str: String) -> bool {32	str.is_empty()33}3435#[builtin]36pub fn builtin_equals_ignore_case(x: String, y: String) -> bool {37	x.to_ascii_lowercase() == y.to_ascii_lowercase()38}3940#[builtin]41pub fn builtin_splitlimit(str: IStr, c: IStr, maxsplits: Either![usize, M1]) -> ArrValue {42	use Either2::*;43	match maxsplits {44		A(n) => str45			.splitn(n + 1, &c as &str)46			.map(|s| Val::Str(StrValue::Flat(s.into())))47			.collect(),48		B(_) => str49			.split(&c as &str)50			.map(|s| Val::Str(StrValue::Flat(s.into())))51			.collect(),52	}53}5455#[builtin]56pub fn builtin_ascii_upper(str: IStr) -> String {57	str.to_ascii_uppercase()58}5960#[builtin]61pub fn builtin_ascii_lower(str: IStr) -> String {62	str.to_ascii_lowercase()63}6465#[builtin]66pub fn builtin_find_substr(pat: IStr, str: IStr) -> ArrValue {67	if pat.is_empty() || str.is_empty() || pat.len() > str.len() {68		return ArrValue::empty();69	}7071	let str = str.as_str();72	let pat = pat.as_bytes();73	let strb = str.as_bytes();7475	let max_pos = str.len() - pat.len();7677	let mut out: Vec<Val> = Vec::new();78	for (ch_idx, (i, _)) in str79		.char_indices()80		.take_while(|(i, _)| i <= &max_pos)81		.enumerate()82	{83		if &strb[i..i + pat.len()] == pat {84			out.push(Val::Num(ch_idx as f64))85		}86	}87	out.into()88}8990#[builtin]91pub fn builtin_parse_int(str: IStr) -> Result<f64> {92	if let Some(raw) = str.strip_prefix('-') {93		if raw.is_empty() {94			throw!("integer only consists of a minus")95		}9697		parse_nat::<10>(raw).map(|value| -value)98	} else {99		if str.is_empty() {100			throw!("empty integer")101		}102103		parse_nat::<10>(str.as_str())104	}105}106107#[builtin]108pub fn builtin_parse_octal(str: IStr) -> Result<f64> {109	if str.is_empty() {110		throw!("empty octal integer");111	}112113	parse_nat::<8>(str.as_str())114}115116#[builtin]117pub fn builtin_parse_hex(str: IStr) -> Result<f64> {118	if str.is_empty() {119		throw!("empty hexadecimal integer");120	}121122	parse_nat::<16>(str.as_str())123}124125fn parse_nat<const BASE: u32>(raw: &str) -> Result<f64> {126	debug_assert!(127		1 <= BASE && BASE <= 16,128		"integer base should be between 1 and 16"129	);130131	const ZERO_CODE: u32 = '0' as u32;132	const UPPER_A_CODE: u32 = 'A' as u32;133	const LOWER_A_CODE: u32 = 'a' as u32;134135	#[inline]136	fn checked_sub_if(condition: bool, lhs: u32, rhs: u32) -> Option<u32> {137		if condition {138			lhs.checked_sub(rhs)139		} else {140			None141		}142	}143144	let base = BASE as f64;145146	raw.chars().try_fold(0f64, |aggregate, digit| {147		let digit = digit as u32;148		let digit = if let Some(digit) = checked_sub_if(BASE > 10, digit, LOWER_A_CODE) {149			digit + 10150		} else if let Some(digit) = checked_sub_if(BASE > 10, digit, UPPER_A_CODE) {151			digit + 10152		} else {153			digit.checked_sub(ZERO_CODE).unwrap_or(BASE)154		};155156		if digit < BASE {157			Ok(base * aggregate + digit as f64)158		} else {159			throw!("{raw:?} is not a base {BASE} integer",);160		}161	})162}163164#[cfg(feature = "exp-bigint")]165#[builtin]166pub fn builtin_bigint(v: Either![f64, IStr]) -> Result<Val> {167	use Either2::*;168	Ok(match v {169		A(a) => Val::BigInt(Box::new((a as i64).into())),170		B(b) => Val::BigInt(Box::new(171			b.as_str()172				.parse()173				.map_err(|e| RuntimeError(format!("bad bigint: {e}").into()))?,174		)),175	})176}177178#[cfg(test)]179mod tests {180	use super::*;181182	#[test]183	fn parse_nat_base_8() {184		assert_eq!(parse_nat::<8>("0").unwrap(), 0.);185		assert_eq!(parse_nat::<8>("5").unwrap(), 5.);186		assert_eq!(parse_nat::<8>("32").unwrap(), 0o32 as f64);187		assert_eq!(parse_nat::<8>("761").unwrap(), 0o761 as f64);188	}189190	#[test]191	fn parse_nat_base_10() {192		assert_eq!(parse_nat::<10>("0").unwrap(), 0.);193		assert_eq!(parse_nat::<10>("3").unwrap(), 3.);194		assert_eq!(parse_nat::<10>("27").unwrap(), 27.);195		assert_eq!(parse_nat::<10>("123").unwrap(), 123.);196	}197198	#[test]199	fn parse_nat_base_16() {200		assert_eq!(parse_nat::<16>("0").unwrap(), 0.);201		assert_eq!(parse_nat::<16>("A").unwrap(), 10.);202		assert_eq!(parse_nat::<16>("a9").unwrap(), 0xA9 as f64);203		assert_eq!(parse_nat::<16>("BbC").unwrap(), 0xBBC as f64);204	}205}
after · crates/jrsonnet-stdlib/src/strings.rs
1use jrsonnet_evaluator::{2	error::{ErrorKind::*, Result},3	function::builtin,4	throw,5	typed::{Either2, M1},6	val::{ArrValue, StrValue},7	Either, IStr, Val,8};910#[builtin]11pub const fn builtin_codepoint(str: char) -> u32 {12	str as u3213}1415#[builtin]16pub fn builtin_substr(str: IStr, from: usize, len: usize) -> String {17	str.chars().skip(from).take(len).collect()18}1920#[builtin]21pub fn builtin_char(n: u32) -> Result<char> {22	Ok(std::char::from_u32(n).ok_or_else(|| InvalidUnicodeCodepointGot(n))?)23}2425#[builtin]26pub fn builtin_str_replace(str: String, from: IStr, to: IStr) -> String {27	str.replace(&from as &str, &to as &str)28}2930#[builtin]31pub fn builtin_is_empty(str: String) -> bool {32	str.is_empty()33}3435#[builtin]36pub fn builtin_equals_ignore_case(str1: String, str2: String) -> bool {37	str1.to_ascii_lowercase() == str2.to_ascii_lowercase()38}3940#[builtin]41pub fn builtin_splitlimit(str: IStr, c: IStr, maxsplits: Either![usize, M1]) -> ArrValue {42	use Either2::*;43	match maxsplits {44		A(n) => str45			.splitn(n + 1, &c as &str)46			.map(|s| Val::Str(StrValue::Flat(s.into())))47			.collect(),48		B(_) => str49			.split(&c as &str)50			.map(|s| Val::Str(StrValue::Flat(s.into())))51			.collect(),52	}53}5455#[builtin]56pub fn builtin_ascii_upper(str: IStr) -> String {57	str.to_ascii_uppercase()58}5960#[builtin]61pub fn builtin_ascii_lower(str: IStr) -> String {62	str.to_ascii_lowercase()63}6465#[builtin]66pub fn builtin_find_substr(pat: IStr, str: IStr) -> ArrValue {67	if pat.is_empty() || str.is_empty() || pat.len() > str.len() {68		return ArrValue::empty();69	}7071	let str = str.as_str();72	let pat = pat.as_bytes();73	let strb = str.as_bytes();7475	let max_pos = str.len() - pat.len();7677	let mut out: Vec<Val> = Vec::new();78	for (ch_idx, (i, _)) in str79		.char_indices()80		.take_while(|(i, _)| i <= &max_pos)81		.enumerate()82	{83		if &strb[i..i + pat.len()] == pat {84			out.push(Val::Num(ch_idx as f64))85		}86	}87	out.into()88}8990#[builtin]91pub fn builtin_parse_int(str: IStr) -> Result<f64> {92	if let Some(raw) = str.strip_prefix('-') {93		if raw.is_empty() {94			throw!("integer only consists of a minus")95		}9697		parse_nat::<10>(raw).map(|value| -value)98	} else {99		if str.is_empty() {100			throw!("empty integer")101		}102103		parse_nat::<10>(str.as_str())104	}105}106107#[builtin]108pub fn builtin_parse_octal(str: IStr) -> Result<f64> {109	if str.is_empty() {110		throw!("empty octal integer");111	}112113	parse_nat::<8>(str.as_str())114}115116#[builtin]117pub fn builtin_parse_hex(str: IStr) -> Result<f64> {118	if str.is_empty() {119		throw!("empty hexadecimal integer");120	}121122	parse_nat::<16>(str.as_str())123}124125fn parse_nat<const BASE: u32>(raw: &str) -> Result<f64> {126	debug_assert!(127		1 <= BASE && BASE <= 16,128		"integer base should be between 1 and 16"129	);130131	const ZERO_CODE: u32 = '0' as u32;132	const UPPER_A_CODE: u32 = 'A' as u32;133	const LOWER_A_CODE: u32 = 'a' as u32;134135	#[inline]136	fn checked_sub_if(condition: bool, lhs: u32, rhs: u32) -> Option<u32> {137		if condition {138			lhs.checked_sub(rhs)139		} else {140			None141		}142	}143144	let base = BASE as f64;145146	raw.chars().try_fold(0f64, |aggregate, digit| {147		let digit = digit as u32;148		let digit = if let Some(digit) = checked_sub_if(BASE > 10, digit, LOWER_A_CODE) {149			digit + 10150		} else if let Some(digit) = checked_sub_if(BASE > 10, digit, UPPER_A_CODE) {151			digit + 10152		} else {153			digit.checked_sub(ZERO_CODE).unwrap_or(BASE)154		};155156		if digit < BASE {157			Ok(base * aggregate + digit as f64)158		} else {159			throw!("{raw:?} is not a base {BASE} integer",);160		}161	})162}163164#[cfg(feature = "exp-bigint")]165#[builtin]166pub fn builtin_bigint(v: Either![f64, IStr]) -> Result<Val> {167	use Either2::*;168	Ok(match v {169		A(a) => Val::BigInt(Box::new((a as i64).into())),170		B(b) => Val::BigInt(Box::new(171			b.as_str()172				.parse()173				.map_err(|e| RuntimeError(format!("bad bigint: {e}").into()))?,174		)),175	})176}177178#[cfg(test)]179mod tests {180	use super::*;181182	#[test]183	fn parse_nat_base_8() {184		assert_eq!(parse_nat::<8>("0").unwrap(), 0.);185		assert_eq!(parse_nat::<8>("5").unwrap(), 5.);186		assert_eq!(parse_nat::<8>("32").unwrap(), 0o32 as f64);187		assert_eq!(parse_nat::<8>("761").unwrap(), 0o761 as f64);188	}189190	#[test]191	fn parse_nat_base_10() {192		assert_eq!(parse_nat::<10>("0").unwrap(), 0.);193		assert_eq!(parse_nat::<10>("3").unwrap(), 3.);194		assert_eq!(parse_nat::<10>("27").unwrap(), 27.);195		assert_eq!(parse_nat::<10>("123").unwrap(), 123.);196	}197198	#[test]199	fn parse_nat_base_16() {200		assert_eq!(parse_nat::<16>("0").unwrap(), 0.);201		assert_eq!(parse_nat::<16>("A").unwrap(), 10.);202		assert_eq!(parse_nat::<16>("a9").unwrap(), 0xA9 as f64);203		assert_eq!(parse_nat::<16>("BbC").unwrap(), 0xBBC as f64);204	}205}
modifiedtests/suite/std_param_names.jsonnetdiffbeforeafterboth
--- a/tests/suite/std_param_names.jsonnet
+++ b/tests/suite/std_param_names.jsonnet
@@ -126,8 +126,33 @@
     decodeUTF8: ['arr'],
 
     sum: ['arr'],
+    avg: ['arr', 'onEmpty'],
+    minArray: ['arr', 'keyF', 'onEmpty'],
+    maxArray: ['arr', 'keyF', 'onEmpty'],
+    remove: ['arr', 'elem'],
+    contains: ['arr', 'elem'],
+    removeAt: ['arr', 'at'],
+
+    equalsIgnoreCase: ['str1', 'str2'],
+    isEmpty: ['str'],
+
     xor: ['x', 'y'],
+    xnor: ['x', 'y'],
+    isInteger: ['x'],
+    isDecimal: ['x'],
+    isEven: ['x'],
+    isOdd: ['x'],
+    round: ['x'],
 
+    sha1: ['str'],
+    sha256: ['str'],
+    sha512: ['str'],
+    sha3: ['str'],
+
+    objectKeysValues: ['o'],
+    objectKeysValuesAll: ['o'],
+    objectRemoveKey: ['obj', 'key'],
+
     // C++ jsonnet undocumented
     __compare: ['v1', 'v2'],
     __compare_array: ['arr1', 'arr2'],
@@ -138,3 +163,9 @@
 };
 
 std.all(std.map(function(key) assertNames(key, names[key]), std.objectFields(names)))
+&& std.all([
+    assert std.objectHasAll(names, key): ('function "%s" is not defined in names'
+        % key); true,
+    for key in std.objectFieldsAll(std)
+    if key != 'thisFile'
+])