From b63c39c2e1285f4251e5aba20f51449439d350b2 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Sat, 15 Jul 2023 18:26:33 +0000 Subject: [PATCH] Merge pull request #124 from pawelbeza/missing-std-features --- --- a/Cargo.lock +++ b/Cargo.lock @@ -375,7 +375,9 @@ "serde", "serde_json", "serde_yaml_with_quirks", + "sha1", "sha2", + "sha3", "structdump", ] @@ -388,6 +390,15 @@ ] [[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] name = "libc" version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -676,6 +687,17 @@ ] [[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] name = "sha2" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -687,6 +709,16 @@ ] [[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] name = "smallvec" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" --- a/crates/jrsonnet-stdlib/Cargo.toml +++ b/crates/jrsonnet-stdlib/Cargo.toml @@ -32,8 +32,12 @@ # std.md5 md5 = "0.7.0" +# std.sha1 +sha1 = "0.10.5" # std.sha256, std.sha512 sha2 = "0.10.6" +# std.sha3 +sha3 = "0.10.8" # std.base64 base64 = "0.21.0" # std.parseJson --- a/crates/jrsonnet-stdlib/src/arrays.rs +++ b/crates/jrsonnet-stdlib/src/arrays.rs @@ -253,3 +253,26 @@ } Ok(Val::Num(arr.iter().sum::() / (arr.len() as f64))) } + +#[builtin] +pub fn builtin_remove_at( + arr: ArrValue, + index: usize, +) -> Result { + let newArrLeft = arr.clone().slice(None, Some(index), None); + let newArrRight = arr.clone().slice(Some(index + 1), None, None); + return Ok(ArrValue::extended( + newArrLeft.unwrap_or(ArrValue::empty()), + newArrRight.unwrap_or(ArrValue::empty())) + ); +} + +#[builtin] +pub fn builtin_remove(arr: ArrValue, elem: Val) -> Result { + for (index, item) in arr.iter().enumerate() { + if equals(&item?, &elem)? { + return builtin_remove_at(arr.clone(), index) + } + } + Ok(arr) +} --- a/crates/jrsonnet-stdlib/src/hash.rs +++ b/crates/jrsonnet-stdlib/src/hash.rs @@ -16,3 +16,15 @@ use sha2::digest::Digest; format!("{:x}", sha2::Sha512::digest(s.as_bytes())) } + +#[builtin] +pub fn builtin_sha1(s: IStr) -> String { + use sha1::digest::Digest; + format!("{:x}", sha1::Sha1::digest(s.as_bytes())) +} + +#[builtin] +pub fn builtin_sha3(s: IStr) -> String { + use sha3::digest::Digest; + format!("{:x}", sha3::Sha3_512::digest(s.as_bytes())) +} --- a/crates/jrsonnet-stdlib/src/lib.rs +++ b/crates/jrsonnet-stdlib/src/lib.rs @@ -83,6 +83,8 @@ ("contains", builtin_member::INST), ("count", builtin_count::INST), ("avg", builtin_avg::INST), + ("removeAt", builtin_remove_at::INST), + ("remove", builtin_remove::INST), // Math ("abs", builtin_abs::INST), ("sign", builtin_sign::INST), @@ -104,11 +106,17 @@ ("exp", builtin_exp::INST), ("mantissa", builtin_mantissa::INST), ("exponent", builtin_exponent::INST), + ("round", builtin_round::INST), + ("isEven", builtin_is_even::INST), + ("isOdd", builtin_is_odd::INST), + ("isInteger", builtin_is_integer::INST), + ("isDecimal", builtin_is_decimal::INST), // Operator ("mod", builtin_mod::INST), ("primitiveEquals", builtin_primitive_equals::INST), ("equals", builtin_equals::INST), ("xor", builtin_xor::INST), + ("xnor", builtin_xnor::INST), ("format", builtin_format::INST), // Sort ("sort", builtin_sort::INST), @@ -118,8 +126,10 @@ ("maxArray", builtin_max_array::INST), // Hash ("md5", builtin_md5::INST), + ("sha1", builtin_sha1::INST), ("sha256", builtin_sha256::INST), ("sha512", builtin_sha512::INST), + ("sha3", builtin_sha3::INST), // Encoding ("encodeUTF8", builtin_encode_utf8::INST), ("decodeUTF8", builtin_decode_utf8::INST), @@ -129,6 +139,7 @@ // Objects ("objectFieldsEx", builtin_object_fields_ex::INST), ("objectHasEx", builtin_object_has_ex::INST), + ("objectRemoveKey", builtin_object_remove_key::INST), // Manifest ("escapeStringJson", builtin_escape_string_json::INST), ("manifestJsonEx", builtin_manifest_json_ex::INST), @@ -142,6 +153,8 @@ ("substr", builtin_substr::INST), ("char", builtin_char::INST), ("strReplace", builtin_str_replace::INST), + ("isEmpty", builtin_is_empty::INST), + ("equalsIgnoreCase", builtin_equals_ignore_case::INST), ("splitLimit", builtin_splitlimit::INST), ("asciiUpper", builtin_ascii_upper::INST), ("asciiLower", builtin_ascii_lower::INST), --- a/crates/jrsonnet-stdlib/src/math.rs +++ b/crates/jrsonnet-stdlib/src/math.rs @@ -114,3 +114,28 @@ pub fn builtin_exponent(x: f64) -> i16 { frexp(x).1 } + +#[builtin] +pub fn builtin_round(x: f64) -> f64 { + x.round() +} + +#[builtin] +pub fn builtin_is_even(x: f64) -> bool { + builtin_round(x) % 2.0 == 0.0 +} + +#[builtin] +pub fn builtin_is_odd(x: f64) -> bool { + builtin_round(x) % 2.0 == 1.0 +} + +#[builtin] +pub fn builtin_is_integer(x: f64) -> bool { + builtin_round(x) == x +} + +#[builtin] +pub fn builtin_is_decimal(x: f64) -> bool { + builtin_round(x) != x +} --- a/crates/jrsonnet-stdlib/src/objects.rs +++ b/crates/jrsonnet-stdlib/src/objects.rs @@ -1,9 +1,10 @@ use jrsonnet_evaluator::{ function::builtin, val::{StrValue, Val}, - IStr, ObjValue, + IStr, ObjValue, ObjValueBuilder, }; + #[builtin] pub fn builtin_object_fields_ex( obj: ObjValue, @@ -27,3 +28,16 @@ pub fn builtin_object_has_ex(obj: ObjValue, fname: IStr, hidden: bool) -> bool { obj.has_field_ex(fname, hidden) } + +#[builtin] +pub fn builtin_object_remove_key(obj: ObjValue, key: IStr) -> ObjValue { + let mut new_obj = ObjValueBuilder::with_capacity(obj.len() - 1); + for (k, v) in obj.iter() { + if k == key { + continue + } + new_obj.member(k).value_unchecked(v.unwrap()) + } + + new_obj.build() +} --- a/crates/jrsonnet-stdlib/src/operator.rs +++ b/crates/jrsonnet-stdlib/src/operator.rs @@ -39,6 +39,11 @@ } #[builtin] +pub fn builtin_xnor(x: bool, y: bool) -> bool { + x == y +} + +#[builtin] pub fn builtin_format(str: IStr, vals: Val) -> Result { std_format(&str, vals) } --- a/crates/jrsonnet-stdlib/src/std.jsonnet +++ b/crates/jrsonnet-stdlib/src/std.jsonnet @@ -274,6 +274,12 @@ objectValuesAll(o):: [o[k] for k in std.objectFieldsAll(o)], + objectKeysValues(o):: + [{ key: k, value: o[k] } for k in std.objectFields(o)], + + objectKeysValuesAll(o):: + [{ key: k, value: o[k] } for k in std.objectFieldsAll(o)], + resolvePath(f, r):: local arr = std.split(f, '/'); std.join('/', std.makeArray(std.length(arr) - 1, function(i) arr[i]) + [r]), --- a/crates/jrsonnet-stdlib/src/strings.rs +++ b/crates/jrsonnet-stdlib/src/strings.rs @@ -28,6 +28,16 @@ } #[builtin] +pub fn builtin_is_empty(str: String) -> bool { + str.is_empty() +} + +#[builtin] +pub fn builtin_equals_ignore_case(x: String, y: String) -> bool { + x.to_ascii_lowercase() == y.to_ascii_lowercase() +} + +#[builtin] pub fn builtin_splitlimit(str: IStr, c: IStr, maxsplits: Either![usize, M1]) -> ArrValue { use Either2::*; match maxsplits { -- gitstuff