diff --git a/Cargo.lock b/Cargo.lock index 773739b..ce2a791 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -837,6 +837,7 @@ dependencies = [ "tokio", "tokio-tungstenite", "toml", + "urlencoding", ] [[package]] @@ -1851,6 +1852,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" + [[package]] name = "utf-8" version = "0.7.6" diff --git a/docs/luneTypes.d.luau b/docs/luneTypes.d.luau index 4f60b68..ad788bf 100644 --- a/docs/luneTypes.d.luau +++ b/docs/luneTypes.d.luau @@ -367,6 +367,28 @@ declare net: { @return The decoded lua value ]=] jsonDecode: (encoded: string) -> any, + --[=[ + @within Net + @must_use + + Encodes the given string using URL encoding. + + @param s The string to encode + @param binary If the string should be treated as binary data and/or is not valid utf-8. Defaults to false + @return The encoded string + ]=] + urlEncode: (s: string, binary: boolean?) -> string, + --[=[ + @within Net + @must_use + + Decodes the given string using URL decoding. + + @param s The string to decode + @param binary If the string should be treated as binary data and/or is not valid utf-8. Defaults to false + @return The decoded string + ]=] + urlDecode: (s: string, binary: boolean?) -> string, } -- TODO: Somehow link this up to require("@lune/serde") diff --git a/packages/lib/Cargo.toml b/packages/lib/Cargo.toml index 2e10754..652ab21 100644 --- a/packages/lib/Cargo.toml +++ b/packages/lib/Cargo.toml @@ -39,6 +39,7 @@ directories = "4.0" dunce = "1.0" pin-project = "1.0" os_str_bytes = "6.4" +urlencoding = "2.1.2" hyper = { version = "0.14", features = ["full"] } hyper-tungstenite = { version = "0.9" } diff --git a/packages/lib/src/globals/net.rs b/packages/lib/src/globals/net.rs index 0c1f8a4..413f966 100644 --- a/packages/lib/src/globals/net.rs +++ b/packages/lib/src/globals/net.rs @@ -31,6 +31,8 @@ pub fn create(lua: &'static Lua) -> LuaResult { .with_async_function("request", net_request)? .with_async_function("socket", net_socket)? .with_async_function("serve", net_serve)? + .with_function("urlEncode", net_url_encode)? + .with_function("urlDecode", net_url_decode)? .build_readonly() } @@ -159,3 +161,27 @@ async fn net_serve<'a>( .with_function("stop", handle_stop)? .build_readonly() } + +fn net_url_encode<'a>( + lua: &'static Lua, + (lua_string, as_binary): (LuaString<'a>, Option), +) -> LuaResult> { + if matches!(as_binary, Some(true)) { + urlencoding::encode_binary(lua_string.as_bytes()).to_lua(lua) + } else { + urlencoding::encode(lua_string.to_str()?).to_lua(lua) + } +} + +fn net_url_decode<'a>( + lua: &'static Lua, + (lua_string, as_binary): (LuaString<'a>, Option), +) -> LuaResult> { + if matches!(as_binary, Some(true)) { + urlencoding::decode_binary(lua_string.as_bytes()).to_lua(lua) + } else { + urlencoding::decode(lua_string.to_str()?) + .map_err(|e| LuaError::RuntimeError(format!("Encountered invalid encoding - {e}")))? + .to_lua(lua) + } +} diff --git a/packages/lib/src/tests.rs b/packages/lib/src/tests.rs index 3738b7c..3c8bcda 100644 --- a/packages/lib/src/tests.rs +++ b/packages/lib/src/tests.rs @@ -51,6 +51,8 @@ create_tests! { net_request_methods: "net/request/methods", net_request_query: "net/request/query", net_request_redirect: "net/request/redirect", + net_url_encode: "net/url/encode", + net_url_decode: "net/url/decode", net_serve_requests: "net/serve/requests", net_serve_websockets: "net/serve/websockets", process_args: "process/args", diff --git a/tests/net/url/decode.luau b/tests/net/url/decode.luau new file mode 100644 index 0000000..7646894 --- /dev/null +++ b/tests/net/url/decode.luau @@ -0,0 +1,2 @@ +local decoded = net.urlDecode("%F0%9F%9A%80%20This%20string%20will%20be%20decoded.") +assert(decoded == "🚀 This string will be decoded.") diff --git a/tests/net/url/encode.luau b/tests/net/url/encode.luau new file mode 100644 index 0000000..6a2f049 --- /dev/null +++ b/tests/net/url/encode.luau @@ -0,0 +1,2 @@ +local encoded = net.urlEncode("🚀 This string will be encoded.") +assert(encoded == "%F0%9F%9A%80%20This%20string%20will%20be%20encoded.")