git.delta.rocks / jrsonnet / refs/commits / 103c2a57d922

difftreelog

feat add std regex builtins

Yaroslav Bolyukin2023-06-15parent: #11193ce.patch.diff
in: master
Upstream issue: https://github.com/google/jsonnet/pull/1039

8 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -30,6 +30,15 @@
 ]
 
 [[package]]
+name = "aho-corasick"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
 name = "allocator-api2"
 version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -37,9 +46,9 @@
 
 [[package]]
 name = "annotate-snippets"
-version = "0.9.1"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3b9d411ecbaf79885c6df4d75fff75858d5995ff25385657a28af47e82f9c36"
+checksum = "ccaf7e9dfbb6ab22c82e473cd1a8a7bd313c19a5b7e40970f3d89ef5a5c9e81e"
 dependencies = [
  "unicode-width",
  "yansi-term",
@@ -47,9 +56,9 @@
 
 [[package]]
 name = "anstream"
-version = "0.6.4"
+version = "0.6.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
+checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
 dependencies = [
  "anstyle",
  "anstyle-parse",
@@ -67,30 +76,30 @@
 
 [[package]]
 name = "anstyle-parse"
-version = "0.2.2"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"
+checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
 dependencies = [
  "utf8parse",
 ]
 
 [[package]]
 name = "anstyle-query"
-version = "1.0.0"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
+checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
 dependencies = [
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
 name = "anstyle-wincon"
-version = "3.0.1"
+version = "3.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
+checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
 dependencies = [
  "anstyle",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -206,9 +215,9 @@
 
 [[package]]
 name = "clap"
-version = "4.4.7"
+version = "4.4.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"
+checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -216,9 +225,9 @@
 
 [[package]]
 name = "clap_builder"
-version = "4.4.7"
+version = "4.4.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"
+checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb"
 dependencies = [
  "anstream",
  "anstyle",
@@ -244,7 +253,7 @@
  "heck",
  "proc-macro2",
  "quote",
- "syn 2.0.38",
+ "syn 2.0.39",
 ]
 
 [[package]]
@@ -344,7 +353,7 @@
 dependencies = [
  "anyhow",
  "bumpalo",
- "indexmap 2.0.2",
+ "indexmap 2.1.0",
  "rustc-hash",
  "serde",
  "unicode-width",
@@ -376,12 +385,12 @@
 
 [[package]]
 name = "errno"
-version = "0.3.5"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
+checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
 dependencies = [
  "libc",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -398,9 +407,9 @@
 
 [[package]]
 name = "form_urlencoded"
-version = "1.2.0"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
 dependencies = [
  "percent-encoding",
 ]
@@ -428,9 +437,9 @@
 
 [[package]]
 name = "getrandom"
-version = "0.2.10"
+version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
+checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
 dependencies = [
  "cfg-if",
  "libc",
@@ -439,9 +448,9 @@
 
 [[package]]
 name = "gimli"
-version = "0.28.0"
+version = "0.28.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
+checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
 
 [[package]]
 name = "hashbrown"
@@ -451,9 +460,18 @@
 
 [[package]]
 name = "hashbrown"
-version = "0.14.2"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.14.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
+checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
 dependencies = [
  "ahash",
  "allocator-api2",
@@ -473,9 +491,9 @@
 
 [[package]]
 name = "idna"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
 dependencies = [
  "unicode-bidi",
  "unicode-normalization",
@@ -493,12 +511,12 @@
 
 [[package]]
 name = "indexmap"
-version = "2.0.2"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
+checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
 dependencies = [
  "equivalent",
- "hashbrown 0.14.2",
+ "hashbrown 0.14.3",
  "serde",
 ]
 
@@ -549,9 +567,9 @@
 
 [[package]]
 name = "itoa"
-version = "1.0.9"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
 
 [[package]]
 name = "jrsonnet"
@@ -589,7 +607,7 @@
  "anyhow",
  "bincode",
  "derivative",
- "hashbrown 0.14.2",
+ "hashbrown 0.14.3",
  "jrsonnet-gcmodule",
  "jrsonnet-interner",
  "jrsonnet-macros",
@@ -643,7 +661,7 @@
 name = "jrsonnet-interner"
 version = "0.5.0-pre95"
 dependencies = [
- "hashbrown 0.14.2",
+ "hashbrown 0.14.3",
  "jrsonnet-gcmodule",
  "rustc-hash",
  "serde",
@@ -669,7 +687,7 @@
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.38",
+ "syn 2.0.39",
 ]
 
 [[package]]
@@ -709,8 +727,11 @@
  "jrsonnet-gcmodule",
  "jrsonnet-macros",
  "jrsonnet-parser",
+ "lru",
  "md5",
  "num-bigint",
+ "regex",
+ "rustc-hash",
  "serde",
  "serde_json",
  "serde_yaml_with_quirks",
@@ -745,9 +766,9 @@
 
 [[package]]
 name = "libc"
-version = "0.2.149"
+version = "0.2.151"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
+checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
 
 [[package]]
 name = "libjsonnet"
@@ -767,9 +788,9 @@
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.4.10"
+version = "0.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"
+checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
 
 [[package]]
 name = "lock_api"
@@ -806,15 +827,24 @@
  "fnv",
  "proc-macro2",
  "quote",
- "regex-syntax",
+ "regex-syntax 0.6.29",
  "syn 1.0.109",
 ]
 
 [[package]]
+name = "lru"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670"
+dependencies = [
+ "hashbrown 0.13.2",
+]
+
+[[package]]
 name = "lsp-server"
-version = "0.7.4"
+version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b52dccdf3302eefab8c8a1273047f0a3c3dca4b527c8458d00c09484c8371928"
+checksum = "fb69ba934913ebf0ef3b3dd762f0149bf993decd571d094b646de09c2e456732"
 dependencies = [
  "crossbeam-channel",
  "log",
@@ -885,7 +915,7 @@
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.38",
+ "syn 2.0.39",
 ]
 
 [[package]]
@@ -958,9 +988,9 @@
 
 [[package]]
 name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
 [[package]]
 name = "owo-colors"
@@ -1026,9 +1056,9 @@
 
 [[package]]
 name = "percent-encoding"
-version = "2.3.0"
+version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
 
 [[package]]
 name = "ppv-lite86"
@@ -1038,9 +1068,9 @@
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.69"
+version = "1.0.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
+checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
 dependencies = [
  "unicode-ident",
 ]
@@ -1114,7 +1144,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
 dependencies = [
- "getrandom 0.2.10",
+ "getrandom 0.2.11",
 ]
 
 [[package]]
@@ -1163,19 +1193,48 @@
 ]
 
 [[package]]
+name = "regex"
+version = "1.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax 0.8.2",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax 0.8.2",
+]
+
+[[package]]
 name = "regex-syntax"
 version = "0.6.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
 
 [[package]]
+name = "regex-syntax"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
+
+[[package]]
 name = "rowan"
-version = "0.15.13"
+version = "0.15.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "906057e449592587bf6724f00155bf82a6752c868d78a8fb3aa41f4e6357cfe8"
+checksum = "32a58fa8a7ccff2aec4f39cc45bf5f985cec7125ab271cf681c279fd00192b49"
 dependencies = [
  "countme",
- "hashbrown 0.12.3",
+ "hashbrown 0.14.3",
  "memoffset",
  "rustc-hash",
  "text-size",
@@ -1195,22 +1254,22 @@
 
 [[package]]
 name = "rustix"
-version = "0.38.21"
+version = "0.38.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
+checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
 dependencies = [
  "bitflags 2.4.1",
  "errno",
  "libc",
  "linux-raw-sys",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
 name = "ryu"
-version = "1.0.15"
+version = "1.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
+checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
 
 [[package]]
 name = "scopeguard"
@@ -1220,29 +1279,29 @@
 
 [[package]]
 name = "serde"
-version = "1.0.190"
+version = "1.0.193"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
+checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.190"
+version = "1.0.193"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
+checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.38",
+ "syn 2.0.39",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.107"
+version = "1.0.108"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
+checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
 dependencies = [
  "itoa",
  "ryu",
@@ -1251,13 +1310,13 @@
 
 [[package]]
 name = "serde_repr"
-version = "0.1.16"
+version = "0.1.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
+checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.38",
+ "syn 2.0.39",
 ]
 
 [[package]]
@@ -1312,9 +1371,9 @@
 
 [[package]]
 name = "smallvec"
-version = "1.11.1"
+version = "1.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
+checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
 
 [[package]]
 name = "smawk"
@@ -1397,9 +1456,9 @@
 
 [[package]]
 name = "syn"
-version = "2.0.38"
+version = "2.0.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
+checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1473,7 +1532,7 @@
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.38",
+ "syn 2.0.39",
 ]
 
 [[package]]
@@ -1505,9 +1564,9 @@
 
 [[package]]
 name = "unicode-bidi"
-version = "0.3.13"
+version = "0.3.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
+checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416"
 
 [[package]]
 name = "unicode-ident"
@@ -1538,9 +1597,9 @@
 
 [[package]]
 name = "url"
-version = "2.4.1"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
+checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
 dependencies = [
  "form_urlencoded",
  "idna",
@@ -1613,6 +1672,15 @@
 ]
 
 [[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.0",
+]
+
+[[package]]
 name = "windows-targets"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1643,6 +1711,21 @@
 ]
 
 [[package]]
+name = "windows-targets"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.0",
+ "windows_aarch64_msvc 0.52.0",
+ "windows_i686_gnu 0.52.0",
+ "windows_i686_msvc 0.52.0",
+ "windows_x86_64_gnu 0.52.0",
+ "windows_x86_64_gnullvm 0.52.0",
+ "windows_x86_64_msvc 0.52.0",
+]
+
+[[package]]
 name = "windows_aarch64_gnullvm"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1655,6 +1738,12 @@
 checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
 [[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
+
+[[package]]
 name = "windows_aarch64_msvc"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1667,6 +1756,12 @@
 checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
+
+[[package]]
 name = "windows_i686_gnu"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1679,6 +1774,12 @@
 checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
+name = "windows_i686_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+
+[[package]]
 name = "windows_i686_msvc"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1691,6 +1792,12 @@
 checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
+name = "windows_i686_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+
+[[package]]
 name = "windows_x86_64_gnu"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1703,6 +1810,12 @@
 checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
+
+[[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1715,6 +1828,12 @@
 checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
+
+[[package]]
 name = "windows_x86_64_msvc"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1727,6 +1846,12 @@
 checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
 
 [[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
+
+[[package]]
 name = "xshell"
 version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1746,7 +1871,7 @@
 version = "0.1.0"
 dependencies = [
  "anyhow",
- "indexmap 2.0.2",
+ "indexmap 2.1.0",
  "itertools",
  "proc-macro2",
  "quote",
@@ -1774,20 +1899,20 @@
 
 [[package]]
 name = "zerocopy"
-version = "0.7.18"
+version = "0.7.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ede7d7c7970ca2215b8c1ccf4d4f354c4733201dfaaba72d44ae5b37472e4901"
+checksum = "306dca4455518f1f31635ec308b6b3e4eb1b11758cefafc782827d0aa7acb5c7"
 dependencies = [
  "zerocopy-derive",
 ]
 
 [[package]]
 name = "zerocopy-derive"
-version = "0.7.18"
+version = "0.7.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b27b1bb92570f989aac0ab7e9cbfbacdd65973f7ee920d9f0e71ebac878fd0b"
+checksum = "be912bf68235a88fbefd1b73415cb218405958d1655b2ece9035a19920bdf6ba"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.38",
+ "syn 2.0.39",
 ]
modifiedCargo.tomldiffbeforeafterboth
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -64,6 +64,9 @@
 lsp-server = "0.7.4"
 lsp-types = "0.94.1"
 
+regex = "1.8.4"
+lru = "0.10.0"
+
 #[profile.test]
 #opt-level = 1
 
modifiedcmds/jrsonnet/Cargo.tomldiffbeforeafterboth
--- a/cmds/jrsonnet/Cargo.toml
+++ b/cmds/jrsonnet/Cargo.toml
@@ -29,6 +29,10 @@
 exp-object-iteration = ["jrsonnet-evaluator/exp-object-iteration"]
 # Bigint type
 exp-bigint = ["jrsonnet-evaluator/exp-bigint", "jrsonnet-cli/exp-bigint"]
+# std.regex and co.
+exp-regex = [
+    "jrsonnet-stdlib/exp-regex",
+]
 # obj?.field, obj?.['field']
 exp-null-coaelse = [
     "jrsonnet-evaluator/exp-null-coaelse",
modifiedcrates/jrsonnet-cli/Cargo.tomldiffbeforeafterboth
--- a/crates/jrsonnet-cli/Cargo.toml
+++ b/crates/jrsonnet-cli/Cargo.toml
@@ -20,6 +20,9 @@
     "jrsonnet-evaluator/exp-null-coaelse",
     "jrsonnet-stdlib/exp-null-coaelse",
 ]
+exp-regex = [
+    "jrsonnet-stdlib/exp-regex",
+]
 legacy-this-file = ["jrsonnet-stdlib/legacy-this-file"]
 
 [dependencies]
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/typed/conversions.rs
+++ b/crates/jrsonnet-evaluator/src/typed/conversions.rs
@@ -304,6 +304,22 @@
 	}
 }
 
+impl Typed for StrValue {
+	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);
+
+	fn into_untyped(value: Self) -> Result<Val> {
+		Ok(Val::Str(value))
+	}
+
+	fn from_untyped(value: Val) -> Result<Self> {
+		<Self as Typed>::TYPE.check(&value)?;
+		match value {
+			Val::Str(s) => Ok(s),
+			_ => unreachable!(),
+		}
+	}
+}
+
 impl Typed for char {
 	const TYPE: &'static ComplexValType = &ComplexValType::Char;
 
modifiedcrates/jrsonnet-stdlib/Cargo.tomldiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/Cargo.toml
+++ b/crates/jrsonnet-stdlib/Cargo.toml
@@ -20,6 +20,8 @@
 exp-bigint = ["num-bigint", "jrsonnet-evaluator/exp-bigint"]
 
 exp-null-coaelse = ["jrsonnet-parser/exp-null-coaelse", "jrsonnet-evaluator/exp-null-coaelse"]
+# std.regexMatch and other helpers
+exp-regex = ["regex", "lru", "rustc-hash"]
 
 [dependencies]
 jrsonnet-evaluator.workspace = true
@@ -49,6 +51,11 @@
 
 num-bigint = { workspace = true, optional = true }
 
+# regex
+regex = { workspace = true, optional = true }
+lru = { workspace = true, optional = true }
+rustc-hash = { workspace = true, optional = true }
+
 [build-dependencies]
 jrsonnet-parser.workspace = true
 structdump = { workspace = true, features = ["derive"] }
modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
before · crates/jrsonnet-stdlib/src/lib.rs
1use std::{2	cell::{Ref, RefCell, RefMut},3	collections::HashMap,4	rc::Rc,5};67use jrsonnet_evaluator::{8	error::{ErrorKind::*, Result},9	function::{CallLocation, FuncVal, TlaArg},10	tb,11	trace::PathResolver,12	ContextBuilder, IStr, ObjValue, ObjValueBuilder, State, Thunk, Val,13};14use jrsonnet_gcmodule::Trace;15use jrsonnet_parser::Source;1617mod expr;18mod types;19pub use types::*;20mod arrays;21pub use arrays::*;22mod math;23pub use math::*;24mod operator;25pub use operator::*;26mod sort;27pub use sort::*;28mod hash;29pub use hash::*;30mod encoding;31pub use encoding::*;32mod objects;33pub use objects::*;34mod manifest;35pub use manifest::*;36mod parse;37pub use parse::*;38mod strings;39pub use strings::*;40mod misc;41pub use misc::*;42mod sets;43pub use sets::*;44mod compat;45pub use compat::*;4647pub fn stdlib_uncached(settings: Rc<RefCell<Settings>>) -> ObjValue {48	let mut builder = ObjValueBuilder::new();4950	let expr = expr::stdlib_expr();51	let eval = jrsonnet_evaluator::evaluate(ContextBuilder::dangerous_empty_state().build(), &expr)52		.expect("stdlib.jsonnet should have no errors")53		.as_obj()54		.expect("stdlib.jsonnet should evaluate to object");5556	builder.with_super(eval);5758	for (name, builtin) in [59		// Types60		("type", builtin_type::INST),61		("isString", builtin_is_string::INST),62		("isNumber", builtin_is_number::INST),63		("isBoolean", builtin_is_boolean::INST),64		("isObject", builtin_is_object::INST),65		("isArray", builtin_is_array::INST),66		("isFunction", builtin_is_function::INST),67		// Arrays68		("makeArray", builtin_make_array::INST),69		("repeat", builtin_repeat::INST),70		("slice", builtin_slice::INST),71		("map", builtin_map::INST),72		("flatMap", builtin_flatmap::INST),73		("filter", builtin_filter::INST),74		("foldl", builtin_foldl::INST),75		("foldr", builtin_foldr::INST),76		("range", builtin_range::INST),77		("join", builtin_join::INST),78		("reverse", builtin_reverse::INST),79		("any", builtin_any::INST),80		("all", builtin_all::INST),81		("member", builtin_member::INST),82		("contains", builtin_contains::INST),83		("count", builtin_count::INST),84		("avg", builtin_avg::INST),85		("removeAt", builtin_remove_at::INST),86		("remove", builtin_remove::INST),87		("flattenArrays", builtin_flatten_arrays::INST),88		("filterMap", builtin_filter_map::INST),89		// Math90		("abs", builtin_abs::INST),91		("sign", builtin_sign::INST),92		("max", builtin_max::INST),93		("min", builtin_min::INST),94		("sum", builtin_sum::INST),95		("modulo", builtin_modulo::INST),96		("floor", builtin_floor::INST),97		("ceil", builtin_ceil::INST),98		("log", builtin_log::INST),99		("pow", builtin_pow::INST),100		("sqrt", builtin_sqrt::INST),101		("sin", builtin_sin::INST),102		("cos", builtin_cos::INST),103		("tan", builtin_tan::INST),104		("asin", builtin_asin::INST),105		("acos", builtin_acos::INST),106		("atan", builtin_atan::INST),107		("atan2", builtin_atan2::INST),108		("exp", builtin_exp::INST),109		("mantissa", builtin_mantissa::INST),110		("exponent", builtin_exponent::INST),111		("round", builtin_round::INST),112		("isEven", builtin_is_even::INST),113		("isOdd", builtin_is_odd::INST),114		("isInteger", builtin_is_integer::INST),115		("isDecimal", builtin_is_decimal::INST),116		// Operator117		("mod", builtin_mod::INST),118		("primitiveEquals", builtin_primitive_equals::INST),119		("equals", builtin_equals::INST),120		("xor", builtin_xor::INST),121		("xnor", builtin_xnor::INST),122		("format", builtin_format::INST),123		// Sort124		("sort", builtin_sort::INST),125		("uniq", builtin_uniq::INST),126		("set", builtin_set::INST),127		("minArray", builtin_min_array::INST),128		("maxArray", builtin_max_array::INST),129		// Hash130		("md5", builtin_md5::INST),131		("sha1", builtin_sha1::INST),132		("sha256", builtin_sha256::INST),133		("sha512", builtin_sha512::INST),134		("sha3", builtin_sha3::INST),135		// Encoding136		("encodeUTF8", builtin_encode_utf8::INST),137		("decodeUTF8", builtin_decode_utf8::INST),138		("base64", builtin_base64::INST),139		("base64Decode", builtin_base64_decode::INST),140		("base64DecodeBytes", builtin_base64_decode_bytes::INST),141		// Objects142		("objectFieldsEx", builtin_object_fields_ex::INST),143		("objectFields", builtin_object_fields::INST),144		("objectFieldsAll", builtin_object_fields_all::INST),145		("objectValues", builtin_object_values::INST),146		("objectValuesAll", builtin_object_values_all::INST),147		("objectKeysValues", builtin_object_keys_values::INST),148		("objectKeysValuesAll", builtin_object_keys_values_all::INST),149		("objectHasEx", builtin_object_has_ex::INST),150		("objectHas", builtin_object_has::INST),151		("objectHasAll", builtin_object_has_all::INST),152		("objectRemoveKey", builtin_object_remove_key::INST),153		// Manifest154		("escapeStringJson", builtin_escape_string_json::INST),155		("manifestJsonEx", builtin_manifest_json_ex::INST),156		("manifestYamlDoc", builtin_manifest_yaml_doc::INST),157		("manifestTomlEx", builtin_manifest_toml_ex::INST),158		("toString", builtin_to_string::INST),159		// Parsing160		("parseJson", builtin_parse_json::INST),161		("parseYaml", builtin_parse_yaml::INST),162		// Strings163		("codepoint", builtin_codepoint::INST),164		("substr", builtin_substr::INST),165		("char", builtin_char::INST),166		("strReplace", builtin_str_replace::INST),167		("isEmpty", builtin_is_empty::INST),168		("equalsIgnoreCase", builtin_equals_ignore_case::INST),169		("splitLimit", builtin_splitlimit::INST),170		("asciiUpper", builtin_ascii_upper::INST),171		("asciiLower", builtin_ascii_lower::INST),172		("findSubstr", builtin_find_substr::INST),173		("parseInt", builtin_parse_int::INST),174		#[cfg(feature = "exp-bigint")]175		("bigint", builtin_bigint::INST),176		("parseOctal", builtin_parse_octal::INST),177		("parseHex", builtin_parse_hex::INST),178		("stringChars", builtin_string_chars::INST),179		// Misc180		("length", builtin_length::INST),181		("startsWith", builtin_starts_with::INST),182		("endsWith", builtin_ends_with::INST),183		// Sets184		("setMember", builtin_set_member::INST),185		("setInter", builtin_set_inter::INST),186		("setDiff", builtin_set_diff::INST),187		("setUnion", builtin_set_union::INST),188		// Compat189		("__compare", builtin___compare::INST),190	]191	.iter()192	.cloned()193	{194		builder.method(name, builtin);195	}196197	builder.method(198		"extVar",199		builtin_ext_var {200			settings: settings.clone(),201		},202	);203	builder.method(204		"native",205		builtin_native {206			settings: settings.clone(),207		},208	);209	builder.method("trace", builtin_trace { settings });210211	builder.method("id", FuncVal::Id);212213	builder.build()214}215216pub trait TracePrinter {217	fn print_trace(&self, loc: CallLocation, value: IStr);218}219220pub struct StdTracePrinter {221	resolver: PathResolver,222}223impl StdTracePrinter {224	pub fn new(resolver: PathResolver) -> Self {225		Self { resolver }226	}227}228impl TracePrinter for StdTracePrinter {229	fn print_trace(&self, loc: CallLocation, value: IStr) {230		eprint!("TRACE:");231		if let Some(loc) = loc.0 {232			let locs = loc.0.map_source_locations(&[loc.1]);233			eprint!(234				" {}:{}",235				match loc.0.source_path().path() {236					Some(p) => self.resolver.resolve(p),237					None => loc.0.source_path().to_string(),238				},239				locs[0].line240			);241		}242		eprintln!(" {value}");243	}244}245246pub struct Settings {247	/// Used for `std.extVar`248	pub ext_vars: HashMap<IStr, TlaArg>,249	/// Used for `std.native`250	pub ext_natives: HashMap<IStr, FuncVal>,251	/// Used for `std.trace`252	pub trace_printer: Box<dyn TracePrinter>,253	/// Used for `std.thisFile`254	pub path_resolver: PathResolver,255}256257fn extvar_source(name: &str, code: impl Into<IStr>) -> Source {258	let source_name = format!("<extvar:{name}>");259	Source::new_virtual(source_name.into(), code.into())260}261262#[derive(Trace, Clone)]263pub struct ContextInitializer {264	/// When we don't need to support legacy-this-file, we can reuse same context for all files265	#[cfg(not(feature = "legacy-this-file"))]266	context: jrsonnet_evaluator::Context,267	/// For `populate`268	#[cfg(not(feature = "legacy-this-file"))]269	stdlib_thunk: Thunk<Val>,270	/// Otherwise, we can only keep first stdlib layer, and then stack thisFile on top of it271	#[cfg(feature = "legacy-this-file")]272	stdlib_obj: ObjValue,273	settings: Rc<RefCell<Settings>>,274}275impl ContextInitializer {276	pub fn new(_s: State, resolver: PathResolver) -> Self {277		let settings = Settings {278			ext_vars: Default::default(),279			ext_natives: Default::default(),280			trace_printer: Box::new(StdTracePrinter::new(resolver.clone())),281			path_resolver: resolver,282		};283		let settings = Rc::new(RefCell::new(settings));284		let stdlib_obj = stdlib_uncached(settings.clone());285		#[cfg(not(feature = "legacy-this-file"))]286		let stdlib_thunk = Thunk::evaluated(Val::Obj(stdlib_obj));287		Self {288			#[cfg(not(feature = "legacy-this-file"))]289			context: {290				let mut context = ContextBuilder::with_capacity(_s, 1);291				context.bind("std", stdlib_thunk.clone());292				context.build()293			},294			#[cfg(not(feature = "legacy-this-file"))]295			stdlib_thunk,296			#[cfg(feature = "legacy-this-file")]297			stdlib_obj,298			settings,299		}300	}301	pub fn settings(&self) -> Ref<Settings> {302		self.settings.borrow()303	}304	pub fn settings_mut(&self) -> RefMut<Settings> {305		self.settings.borrow_mut()306	}307	pub fn add_ext_var(&self, name: IStr, value: Val) {308		self.settings_mut()309			.ext_vars310			.insert(name, TlaArg::Val(value));311	}312	pub fn add_ext_str(&self, name: IStr, value: IStr) {313		self.settings_mut()314			.ext_vars315			.insert(name, TlaArg::String(value));316	}317	pub fn add_ext_code(&self, name: &str, code: impl Into<IStr>) -> Result<()> {318		let code = code.into();319		let source = extvar_source(name, code.clone());320		let parsed = jrsonnet_parser::parse(321			&code,322			&jrsonnet_parser::ParserSettings {323				source: source.clone(),324			},325		)326		.map_err(|e| ImportSyntaxError {327			path: source,328			error: Box::new(e),329		})?;330		// self.data_mut().volatile_files.insert(source_name, code);331		self.settings_mut()332			.ext_vars333			.insert(name.into(), TlaArg::Code(parsed));334		Ok(())335	}336	pub fn add_native(&self, name: impl Into<IStr>, cb: impl Into<FuncVal>) {337		self.settings_mut()338			.ext_natives339			.insert(name.into(), cb.into());340	}341}342impl jrsonnet_evaluator::ContextInitializer for ContextInitializer {343	fn reserve_vars(&self) -> usize {344		1345	}346	#[cfg(not(feature = "legacy-this-file"))]347	fn initialize(&self, _s: State, _source: Source) -> jrsonnet_evaluator::Context {348		self.context.clone()349	}350	#[cfg(not(feature = "legacy-this-file"))]351	fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) {352		builder.bind("std", self.stdlib_thunk.clone());353	}354	#[cfg(feature = "legacy-this-file")]355	fn populate(&self, source: Source, builder: &mut ContextBuilder) {356		use jrsonnet_evaluator::val::StrValue;357358		let mut std = ObjValueBuilder::new();359		std.with_super(self.stdlib_obj.clone());360		std.field("thisFile")361			.hide()362			.value(match source.source_path().path() {363				Some(p) => self.settings().path_resolver.resolve(p),364				None => source.source_path().to_string(),365			});366		let stdlib_with_this_file = std.build();367368		builder.bind("std", Thunk::evaluated(Val::Obj(stdlib_with_this_file)));369	}370	fn as_any(&self) -> &dyn std::any::Any {371		self372	}373}374375pub trait StateExt {376	/// This method was previously implemented in jrsonnet-evaluator itself377	fn with_stdlib(&self);378}379380impl StateExt for State {381	fn with_stdlib(&self) {382		let initializer = ContextInitializer::new(self.clone(), PathResolver::new_cwd_fallback());383		self.settings_mut().context_initializer = tb!(initializer)384	}385}
after · crates/jrsonnet-stdlib/src/lib.rs
1use std::{2	cell::{Ref, RefCell, RefMut},3	collections::HashMap,4	rc::Rc,5};67use jrsonnet_evaluator::{8	error::{ErrorKind::*, Result},9	function::{CallLocation, FuncVal, TlaArg},10	tb,11	trace::PathResolver,12	ContextBuilder, IStr, ObjValue, ObjValueBuilder, State, Thunk, Val,13};14use jrsonnet_gcmodule::Trace;15use jrsonnet_parser::Source;1617mod expr;18mod types;19pub use types::*;20mod arrays;21pub use arrays::*;22mod math;23pub use math::*;24mod operator;25pub use operator::*;26mod sort;27pub use sort::*;28mod hash;29pub use hash::*;30mod encoding;31pub use encoding::*;32mod objects;33pub use objects::*;34mod manifest;35pub use manifest::*;36mod parse;37pub use parse::*;38mod strings;39pub use strings::*;40mod misc;41pub use misc::*;42mod sets;43pub use sets::*;44mod compat;45pub use compat::*;46#[cfg(feature = "exp-regex")]47mod regex;48#[cfg(feature = "exp-regex")]49pub use crate::regex::*;5051pub fn stdlib_uncached(settings: Rc<RefCell<Settings>>) -> ObjValue {52	let mut builder = ObjValueBuilder::new();5354	let expr = expr::stdlib_expr();55	let eval = jrsonnet_evaluator::evaluate(ContextBuilder::dangerous_empty_state().build(), &expr)56		.expect("stdlib.jsonnet should have no errors")57		.as_obj()58		.expect("stdlib.jsonnet should evaluate to object");5960	builder.with_super(eval);6162	for (name, builtin) in [63		// Types64		("type", builtin_type::INST),65		("isString", builtin_is_string::INST),66		("isNumber", builtin_is_number::INST),67		("isBoolean", builtin_is_boolean::INST),68		("isObject", builtin_is_object::INST),69		("isArray", builtin_is_array::INST),70		("isFunction", builtin_is_function::INST),71		// Arrays72		("makeArray", builtin_make_array::INST),73		("repeat", builtin_repeat::INST),74		("slice", builtin_slice::INST),75		("map", builtin_map::INST),76		("flatMap", builtin_flatmap::INST),77		("filter", builtin_filter::INST),78		("foldl", builtin_foldl::INST),79		("foldr", builtin_foldr::INST),80		("range", builtin_range::INST),81		("join", builtin_join::INST),82		("reverse", builtin_reverse::INST),83		("any", builtin_any::INST),84		("all", builtin_all::INST),85		("member", builtin_member::INST),86		("contains", builtin_contains::INST),87		("count", builtin_count::INST),88		("avg", builtin_avg::INST),89		("removeAt", builtin_remove_at::INST),90		("remove", builtin_remove::INST),91		("flattenArrays", builtin_flatten_arrays::INST),92		("filterMap", builtin_filter_map::INST),93		// Math94		("abs", builtin_abs::INST),95		("sign", builtin_sign::INST),96		("max", builtin_max::INST),97		("min", builtin_min::INST),98		("sum", builtin_sum::INST),99		("modulo", builtin_modulo::INST),100		("floor", builtin_floor::INST),101		("ceil", builtin_ceil::INST),102		("log", builtin_log::INST),103		("pow", builtin_pow::INST),104		("sqrt", builtin_sqrt::INST),105		("sin", builtin_sin::INST),106		("cos", builtin_cos::INST),107		("tan", builtin_tan::INST),108		("asin", builtin_asin::INST),109		("acos", builtin_acos::INST),110		("atan", builtin_atan::INST),111		("atan2", builtin_atan2::INST),112		("exp", builtin_exp::INST),113		("mantissa", builtin_mantissa::INST),114		("exponent", builtin_exponent::INST),115		("round", builtin_round::INST),116		("isEven", builtin_is_even::INST),117		("isOdd", builtin_is_odd::INST),118		("isInteger", builtin_is_integer::INST),119		("isDecimal", builtin_is_decimal::INST),120		// Operator121		("mod", builtin_mod::INST),122		("primitiveEquals", builtin_primitive_equals::INST),123		("equals", builtin_equals::INST),124		("xor", builtin_xor::INST),125		("xnor", builtin_xnor::INST),126		("format", builtin_format::INST),127		// Sort128		("sort", builtin_sort::INST),129		("uniq", builtin_uniq::INST),130		("set", builtin_set::INST),131		("minArray", builtin_min_array::INST),132		("maxArray", builtin_max_array::INST),133		// Hash134		("md5", builtin_md5::INST),135		("sha1", builtin_sha1::INST),136		("sha256", builtin_sha256::INST),137		("sha512", builtin_sha512::INST),138		("sha3", builtin_sha3::INST),139		// Encoding140		("encodeUTF8", builtin_encode_utf8::INST),141		("decodeUTF8", builtin_decode_utf8::INST),142		("base64", builtin_base64::INST),143		("base64Decode", builtin_base64_decode::INST),144		("base64DecodeBytes", builtin_base64_decode_bytes::INST),145		// Objects146		("objectFieldsEx", builtin_object_fields_ex::INST),147		("objectFields", builtin_object_fields::INST),148		("objectFieldsAll", builtin_object_fields_all::INST),149		("objectValues", builtin_object_values::INST),150		("objectValuesAll", builtin_object_values_all::INST),151		("objectKeysValues", builtin_object_keys_values::INST),152		("objectKeysValuesAll", builtin_object_keys_values_all::INST),153		("objectHasEx", builtin_object_has_ex::INST),154		("objectHas", builtin_object_has::INST),155		("objectHasAll", builtin_object_has_all::INST),156		("objectRemoveKey", builtin_object_remove_key::INST),157		// Manifest158		("escapeStringJson", builtin_escape_string_json::INST),159		("manifestJsonEx", builtin_manifest_json_ex::INST),160		("manifestYamlDoc", builtin_manifest_yaml_doc::INST),161		("manifestTomlEx", builtin_manifest_toml_ex::INST),162		("toString", builtin_to_string::INST),163		// Parsing164		("parseJson", builtin_parse_json::INST),165		("parseYaml", builtin_parse_yaml::INST),166		// Strings167		("codepoint", builtin_codepoint::INST),168		("substr", builtin_substr::INST),169		("char", builtin_char::INST),170		("strReplace", builtin_str_replace::INST),171		("isEmpty", builtin_is_empty::INST),172		("equalsIgnoreCase", builtin_equals_ignore_case::INST),173		("splitLimit", builtin_splitlimit::INST),174		("asciiUpper", builtin_ascii_upper::INST),175		("asciiLower", builtin_ascii_lower::INST),176		("findSubstr", builtin_find_substr::INST),177		("parseInt", builtin_parse_int::INST),178		#[cfg(feature = "exp-bigint")]179		("bigint", builtin_bigint::INST),180		("parseOctal", builtin_parse_octal::INST),181		("parseHex", builtin_parse_hex::INST),182		("stringChars", builtin_string_chars::INST),183		// Misc184		("length", builtin_length::INST),185		("startsWith", builtin_starts_with::INST),186		("endsWith", builtin_ends_with::INST),187		// Sets188		("setMember", builtin_set_member::INST),189		("setInter", builtin_set_inter::INST),190		("setDiff", builtin_set_diff::INST),191		("setUnion", builtin_set_union::INST),192		// Regex193		#[cfg(feature = "exp-regex")]194		("regexQuoteMeta", builtin_regex_quote_meta::INST),195		// Compat196		("__compare", builtin___compare::INST),197	]198	.iter()199	.cloned()200	{201		builder.method(name, builtin);202	}203204	builder.method(205		"extVar",206		builtin_ext_var {207			settings: settings.clone(),208		},209	);210	builder.method(211		"native",212		builtin_native {213			settings: settings.clone(),214		},215	);216	builder.method("trace", builtin_trace { settings });217	builder.method("id", FuncVal::Id);218219	#[cfg(feature = "exp-regex")]220	{221		// Regex222		let regex_cache = RegexCache::default();223		builder.method(224			"regexFullMatch",225			builtin_regex_full_match {226				cache: regex_cache.clone(),227			},228		);229		builder.method(230			"regexPartialMatch",231			builtin_regex_partial_match {232				cache: regex_cache.clone(),233			},234		);235		builder.method(236			"regexReplace",237			builtin_regex_replace {238				cache: regex_cache.clone(),239			},240		);241		builder.method(242			"regexGlobalReplace",243			builtin_regex_global_replace {244				cache: regex_cache.clone(),245			},246		);247	};248249	builder.build()250}251252pub trait TracePrinter {253	fn print_trace(&self, loc: CallLocation, value: IStr);254}255256pub struct StdTracePrinter {257	resolver: PathResolver,258}259impl StdTracePrinter {260	pub fn new(resolver: PathResolver) -> Self {261		Self { resolver }262	}263}264impl TracePrinter for StdTracePrinter {265	fn print_trace(&self, loc: CallLocation, value: IStr) {266		eprint!("TRACE:");267		if let Some(loc) = loc.0 {268			let locs = loc.0.map_source_locations(&[loc.1]);269			eprint!(270				" {}:{}",271				match loc.0.source_path().path() {272					Some(p) => self.resolver.resolve(p),273					None => loc.0.source_path().to_string(),274				},275				locs[0].line276			);277		}278		eprintln!(" {value}");279	}280}281282pub struct Settings {283	/// Used for `std.extVar`284	pub ext_vars: HashMap<IStr, TlaArg>,285	/// Used for `std.native`286	pub ext_natives: HashMap<IStr, FuncVal>,287	/// Used for `std.trace`288	pub trace_printer: Box<dyn TracePrinter>,289	/// Used for `std.thisFile`290	pub path_resolver: PathResolver,291}292293fn extvar_source(name: &str, code: impl Into<IStr>) -> Source {294	let source_name = format!("<extvar:{name}>");295	Source::new_virtual(source_name.into(), code.into())296}297298#[derive(Trace, Clone)]299pub struct ContextInitializer {300	/// When we don't need to support legacy-this-file, we can reuse same context for all files301	#[cfg(not(feature = "legacy-this-file"))]302	context: jrsonnet_evaluator::Context,303	/// For `populate`304	#[cfg(not(feature = "legacy-this-file"))]305	stdlib_thunk: Thunk<Val>,306	/// Otherwise, we can only keep first stdlib layer, and then stack thisFile on top of it307	#[cfg(feature = "legacy-this-file")]308	stdlib_obj: ObjValue,309	settings: Rc<RefCell<Settings>>,310}311impl ContextInitializer {312	pub fn new(_s: State, resolver: PathResolver) -> Self {313		let settings = Settings {314			ext_vars: Default::default(),315			ext_natives: Default::default(),316			trace_printer: Box::new(StdTracePrinter::new(resolver.clone())),317			path_resolver: resolver,318		};319		let settings = Rc::new(RefCell::new(settings));320		let stdlib_obj = stdlib_uncached(settings.clone());321		#[cfg(not(feature = "legacy-this-file"))]322		let stdlib_thunk = Thunk::evaluated(Val::Obj(stdlib_obj));323		Self {324			#[cfg(not(feature = "legacy-this-file"))]325			context: {326				let mut context = ContextBuilder::with_capacity(_s, 1);327				context.bind("std", stdlib_thunk.clone());328				context.build()329			},330			#[cfg(not(feature = "legacy-this-file"))]331			stdlib_thunk,332			#[cfg(feature = "legacy-this-file")]333			stdlib_obj,334			settings,335		}336	}337	pub fn settings(&self) -> Ref<Settings> {338		self.settings.borrow()339	}340	pub fn settings_mut(&self) -> RefMut<Settings> {341		self.settings.borrow_mut()342	}343	pub fn add_ext_var(&self, name: IStr, value: Val) {344		self.settings_mut()345			.ext_vars346			.insert(name, TlaArg::Val(value));347	}348	pub fn add_ext_str(&self, name: IStr, value: IStr) {349		self.settings_mut()350			.ext_vars351			.insert(name, TlaArg::String(value));352	}353	pub fn add_ext_code(&self, name: &str, code: impl Into<IStr>) -> Result<()> {354		let code = code.into();355		let source = extvar_source(name, code.clone());356		let parsed = jrsonnet_parser::parse(357			&code,358			&jrsonnet_parser::ParserSettings {359				source: source.clone(),360			},361		)362		.map_err(|e| ImportSyntaxError {363			path: source,364			error: Box::new(e),365		})?;366		// self.data_mut().volatile_files.insert(source_name, code);367		self.settings_mut()368			.ext_vars369			.insert(name.into(), TlaArg::Code(parsed));370		Ok(())371	}372	pub fn add_native(&self, name: impl Into<IStr>, cb: impl Into<FuncVal>) {373		self.settings_mut()374			.ext_natives375			.insert(name.into(), cb.into());376	}377}378impl jrsonnet_evaluator::ContextInitializer for ContextInitializer {379	fn reserve_vars(&self) -> usize {380		1381	}382	#[cfg(not(feature = "legacy-this-file"))]383	fn initialize(&self, _s: State, _source: Source) -> jrsonnet_evaluator::Context {384		self.context.clone()385	}386	#[cfg(not(feature = "legacy-this-file"))]387	fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) {388		builder.bind("std", self.stdlib_thunk.clone());389	}390	#[cfg(feature = "legacy-this-file")]391	fn populate(&self, source: Source, builder: &mut ContextBuilder) {392		use jrsonnet_evaluator::val::StrValue;393394		let mut std = ObjValueBuilder::new();395		std.with_super(self.stdlib_obj.clone());396		std.field("thisFile")397			.hide()398			.value(match source.source_path().path() {399				Some(p) => self.settings().path_resolver.resolve(p),400				None => source.source_path().to_string(),401			});402		let stdlib_with_this_file = std.build();403404		builder.bind("std", Thunk::evaluated(Val::Obj(stdlib_with_this_file)));405	}406	fn as_any(&self) -> &dyn std::any::Any {407		self408	}409}410411pub trait StateExt {412	/// This method was previously implemented in jrsonnet-evaluator itself413	fn with_stdlib(&self);414}415416impl StateExt for State {417	fn with_stdlib(&self) {418		let initializer = ContextInitializer::new(self.clone(), PathResolver::new_cwd_fallback());419		self.settings_mut().context_initializer = tb!(initializer)420	}421}
addedcrates/jrsonnet-stdlib/src/regex.rsdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-stdlib/src/regex.rs
@@ -0,0 +1,134 @@
+use std::{cell::RefCell, hash::BuildHasherDefault, num::NonZeroUsize, rc::Rc};
+
+use ::regex::Regex;
+use jrsonnet_evaluator::{
+	error::{ErrorKind::*, Result},
+	val::StrValue,
+	IStr, ObjValueBuilder, Val,
+};
+use jrsonnet_macros::builtin;
+use lru::LruCache;
+use rustc_hash::FxHasher;
+
+pub struct RegexCacheInner {
+	cache: RefCell<LruCache<IStr, Rc<Regex>, BuildHasherDefault<FxHasher>>>,
+}
+impl Default for RegexCacheInner {
+	fn default() -> Self {
+		Self {
+			cache: RefCell::new(LruCache::with_hasher(
+				NonZeroUsize::new(20).unwrap(),
+				BuildHasherDefault::default(),
+			)),
+		}
+	}
+}
+pub type RegexCache = Rc<RegexCacheInner>;
+impl RegexCacheInner {
+	fn parse(&self, pattern: IStr) -> Result<Rc<Regex>> {
+		let mut cache = self.cache.borrow_mut();
+		if let Some(found) = cache.get(&pattern) {
+			return Ok(found.clone());
+		}
+		let regex = Regex::new(&pattern)
+			.map_err(|e| RuntimeError(format!("regex parse failed: {e}").into()))?;
+		let regex = Rc::new(regex);
+		cache.push(pattern, regex.clone());
+		Ok(regex)
+	}
+}
+
+pub fn regex_match_inner(regex: &Regex, str: String) -> Result<Val> {
+	let mut out = ObjValueBuilder::with_capacity(3);
+
+	let mut captures = Vec::with_capacity(regex.captures_len());
+	let mut named_captures = ObjValueBuilder::with_capacity(regex.capture_names().len());
+
+	let Some(captured) = regex.captures(&str) else {
+		return Ok(Val::Null)
+	};
+
+	for ele in captured.iter().skip(1) {
+		if let Some(ele) = ele {
+			captures.push(Val::Str(StrValue::Flat(ele.as_str().into())))
+		} else {
+			captures.push(Val::Str(StrValue::Flat(IStr::empty())))
+		}
+	}
+	for (i, name) in regex
+		.capture_names()
+		.skip(1)
+		.enumerate()
+		.flat_map(|(i, v)| Some((i, v?)))
+	{
+		let capture = captures[i].clone();
+		named_captures.member(name.into()).value(capture)?;
+	}
+
+	out.member("string".into())
+		.value_unchecked(Val::Str(captured.get(0).unwrap().as_str().into()));
+	out.member("captures".into())
+		.value_unchecked(Val::Arr(captures.into()));
+	out.member("namedCaptures".into())
+		.value_unchecked(Val::Obj(named_captures.build()));
+
+	Ok(Val::Obj(out.build()))
+}
+
+#[builtin(fields(
+    cache: RegexCache,
+))]
+pub fn builtin_regex_partial_match(
+	this: &builtin_regex_partial_match,
+	pattern: IStr,
+	str: String,
+) -> Result<Val> {
+	let regex = this.cache.parse(pattern)?;
+	regex_match_inner(&regex, str)
+}
+
+#[builtin(fields(
+    cache: RegexCache,
+))]
+pub fn builtin_regex_full_match(
+	this: &builtin_regex_full_match,
+	pattern: StrValue,
+	str: String,
+) -> Result<Val> {
+	let pattern = format!("^{pattern}$").into();
+	let regex = this.cache.parse(pattern)?;
+	regex_match_inner(&regex, str)
+}
+
+#[builtin]
+pub fn builtin_regex_quote_meta(pattern: String) -> String {
+	regex::escape(&pattern)
+}
+
+#[builtin(fields(
+    cache: RegexCache,
+))]
+pub fn builtin_regex_replace(
+	this: &builtin_regex_replace,
+	str: String,
+	pattern: IStr,
+	to: String,
+) -> Result<String> {
+	let regex = this.cache.parse(pattern)?;
+	let replaced = regex.replace(&str, to);
+	Ok(replaced.to_string())
+}
+
+#[builtin(fields(
+    cache: RegexCache,
+))]
+pub fn builtin_regex_global_replace(
+	this: &builtin_regex_global_replace,
+	str: String,
+	pattern: IStr,
+	to: String,
+) -> Result<String> {
+	let regex = this.cache.parse(pattern)?;
+	let replaced = regex.replace_all(&str, to);
+	Ok(replaced.to_string())
+}