From 4961f49c381aa23ba226ff39a631487f7b0d0283 Mon Sep 17 00:00:00 2001 From: laniakea64 Date: Sat, 18 May 2024 20:36:34 -0400 Subject: [PATCH] Add `encode_uri_component` function (#2052) --- Cargo.lock | 55 ++++++++++++++++++++++++++-------------------- Cargo.toml | 1 + README.md | 3 +++ src/function.rs | 15 +++++++++++++ tests/functions.rs | 9 ++++++++ 5 files changed, 59 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 91c4be6..96b94f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -141,9 +141,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" [[package]] name = "cc" @@ -362,9 +362,9 @@ checksum = "bbbaaaf38131deb9ca518a274a45bfdb8771f139517b073b16c2d3d32ae5037b" [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "env_filter" @@ -536,6 +536,7 @@ dependencies = [ "libc", "log", "num_cpus", + "percent-encoding", "pretty_assertions", "rand", "regex", @@ -569,9 +570,9 @@ checksum = "441225017b106b9f902e97947a6d31e44ebcf274b91bdbfb51e5c477fcd468e5" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libredox" @@ -585,9 +586,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "log" @@ -638,6 +639,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -843,9 +850,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" @@ -861,22 +868,22 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.64", ] [[package]] @@ -929,7 +936,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.64", ] [[package]] @@ -987,7 +994,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.63", + "syn 2.0.64", ] [[package]] @@ -1003,9 +1010,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.63" +version = "2.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f" dependencies = [ "proc-macro2", "quote", @@ -1060,22 +1067,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.64", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 9c200b1..6e3defa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ lexiclean = "0.0.1" libc = "0.2.0" log = "0.4.4" num_cpus = "1.15.0" +percent-encoding = "2.3.1" rand = "0.8.5" regex = "1.10.4" semver = "1.0.20" diff --git a/README.md b/README.md index 371ab19..8eb3452 100644 --- a/README.md +++ b/README.md @@ -1427,6 +1427,9 @@ The process ID is: 420 - `prepend(prefix, s)`master Prepend `prefix` to whitespace-separated strings in `s`. `prepend('src/', 'foo bar baz')` ā†’ `'src/foo src/bar src/baz'` +- `encode_uri_component(s)`master - Percent-encode characters in `s` + except `[A-Za-z0-9_.!~*'()-]`, matching the behavior of the + [JavaScript `encodeURIComponent` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent). - `quote(s)` - Replace all single quotes with `'\''` and prepend and append single quotes to `s`. This is sufficient to escape special characters for many shells, including most Bourne shell descendants. diff --git a/src/function.rs b/src/function.rs index f8fc996..1b657d1 100644 --- a/src/function.rs +++ b/src/function.rs @@ -35,6 +35,7 @@ pub(crate) fn get(name: &str) -> Option { "config_local_directory" => Nullary(|_| dir("local config", dirs::config_local_dir)), "data_directory" => Nullary(|_| dir("data", dirs::data_dir)), "data_local_directory" => Nullary(|_| dir("local data", dirs::data_local_dir)), + "encode_uri_component" => Unary(encode_uri_component), "env" => UnaryOpt(env), "env_var" => Unary(env_var), "env_var_or_default" => Binary(env_var_or_default), @@ -204,6 +205,20 @@ fn dir(name: &'static str, f: fn() -> Option) -> Result } } +fn encode_uri_component(_evaluator: &Evaluator, s: &str) -> Result { + static PERCENT_ENCODE: percent_encoding::AsciiSet = percent_encoding::NON_ALPHANUMERIC + .remove(b'-') + .remove(b'_') + .remove(b'.') + .remove(b'!') + .remove(b'~') + .remove(b'*') + .remove(b'\'') + .remove(b'(') + .remove(b')'); + Ok(percent_encoding::utf8_percent_encode(s, &PERCENT_ENCODE).to_string()) +} + fn env_var(evaluator: &Evaluator, key: &str) -> Result { use std::env::VarError::*; diff --git a/tests/functions.rs b/tests/functions.rs index e134110..614761a 100644 --- a/tests/functions.rs +++ b/tests/functions.rs @@ -793,3 +793,12 @@ fn canonicalize() { .stdout_regex(".*/justfile") .run(); } + +#[test] +fn encode_uri_component() { + Test::new() + .justfile("x := encode_uri_component(\"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\\\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~ \\t\\r\\nšŸŒ\")") + .args(["--evaluate", "x"]) + .stdout("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!%22%23%24%25%26'()*%2B%2C-.%2F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E_%60%7B%7C%7D~%20%09%0D%0A%F0%9F%8C%90") + .run(); +}