From 9e6cd4b0afe940ded5c91b4d13e37e0d3b100b3f Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Tue, 21 Mar 2023 16:48:28 +0100 Subject: [PATCH] Move net encode/decode into serde builtin instead --- CHANGELOG.md | 11 ++++++++-- docs/luneTypes.d.luau | 27 +++++++++++-------------- packages/lib/src/globals/mod.rs | 12 ++++++++--- packages/lib/src/globals/net.rs | 18 ----------------- packages/lib/src/globals/serde.rs | 29 +++++++++++++++++++++++++++ packages/lib/src/tests.rs | 6 ++++-- tests/{net => serde}/json/decode.luau | 0 tests/{net => serde}/json/encode.luau | 22 ++++++++------------ tests/serde/json/source.luau | 18 +++++++++++++++++ tests/serde/toml/decode.luau | 8 ++++++++ tests/serde/toml/encode.luau | 5 +++++ tests/serde/toml/source.luau | 26 ++++++++++++++++++++++++ 12 files changed, 128 insertions(+), 54 deletions(-) create mode 100644 packages/lib/src/globals/serde.rs rename tests/{net => serde}/json/decode.luau (100%) rename tests/{net => serde}/json/encode.luau (61%) create mode 100644 tests/serde/json/source.luau create mode 100644 tests/serde/toml/decode.luau create mode 100644 tests/serde/toml/encode.luau create mode 100644 tests/serde/toml/source.luau diff --git a/CHANGELOG.md b/CHANGELOG.md index 91d0352..d7d544d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,16 +14,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `require` has been reimplemented and overhauled in several ways: - - Builtin modules such as `fs`, `net` and others can now be imported using `require("@lune/fs")`, `require("@lune/net")` ...
- This is the first step towards moving away from adding each library as a global, and allowing Lune to have more built-in libraries. + - Globals such as `fs`, `net` and others can now be imported using `require("@lune/fs")`, `require("@lune/net")` ... + + All new built-ins will be added using this syntax and new built-ins will no longer be available in the global scope, and current globals will stay available as globals until proper editor and LSP support is available to ensure Lune users have a good development experience. This is the first step towards moving away from adding each library as a global, and allowing Lune to have more built-in libraries in general. - Requiring a script is now completely asynchronous and will not block lua threads other than the caller. - Requiring a script will no longer error when using async APIs in the main body of the required script. Behavior otherwise stays the same, and requires are still relative to file unless the special `@` prefix is used. +- Added a `serde` built-in + + This built-in contains previously available functions `encode` and `decode` from the `net` global.
+ Note that this is **_only_** available using the new `require` syntax, and is not available as a global. + ### Removed +- Removed experimental `net.encode` and `net.decode` functions, since they are now available using `require("@lune/serde")` - Removed option to preserve default Luau require behavior ## `0.5.6` - March 11th, 2023 diff --git a/docs/luneTypes.d.luau b/docs/luneTypes.d.luau index 6cc84b3..4f60b68 100644 --- a/docs/luneTypes.d.luau +++ b/docs/luneTypes.d.luau @@ -162,8 +162,6 @@ declare fs: { type NetMethod = "GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "OPTIONS" | "PATCH" -type NetEncodeDecodeFormat = "json" | "yaml" | "toml" - --[=[ @type NetFetchParams @within Net @@ -369,14 +367,17 @@ declare net: { @return The decoded lua value ]=] jsonDecode: (encoded: string) -> any, +} + +-- TODO: Somehow link this up to require("@lune/serde") + +type SerdeEncodeDecodeFormat = "json" | "yaml" | "toml" + +type Serde = { --[=[ - @within Net + @within Serde @must_use - ***WARNING:** Unstable API* - - *This API is unstable and may change or be removed in the next major version of Lune.* - Encodes the given value using the given format. @param format The format to use @@ -384,22 +385,18 @@ declare net: { @param pretty If the encoded string should be human-readable, including things such as newlines and spaces. Only supported for json and toml formats, and defaults to false @return The encoded string ]=] - encode: (format: NetEncodeDecodeFormat, value: any, pretty: boolean?) -> string, + encode: (format: SerdeEncodeDecodeFormat, value: any, pretty: boolean?) -> string, --[=[ - @within Net + @within Serde @must_use - ***WARNING:** Unstable API* - - *This API is unstable and may change or be removed in the next major version of Lune.* - Decodes the given string using the given format into a lua value. @param format The format to use - @param encoded The JSON string to decode + @param encoded The string to decode @return The decoded lua value ]=] - decode: (format: NetEncodeDecodeFormat, encoded: string) -> any, + decode: (format: SerdeEncodeDecodeFormat, encoded: string) -> any, } type ProcessSpawnOptionsStdio = "inherit" | "default" diff --git a/packages/lib/src/globals/mod.rs b/packages/lib/src/globals/mod.rs index f5015f3..ed2b79a 100644 --- a/packages/lib/src/globals/mod.rs +++ b/packages/lib/src/globals/mod.rs @@ -4,24 +4,30 @@ mod fs; mod net; mod process; mod require; +mod serde; mod stdio; mod task; mod top_level; +const BUILTINS_AS_GLOBALS: &[&str] = &["fs", "net", "process", "stdio", "task"]; + pub fn create(lua: &'static Lua, args: Vec) -> LuaResult<()> { // Create all builtins let builtins = vec![ ("fs", fs::create(lua)?), ("net", net::create(lua)?), ("process", process::create(lua, args)?), + ("serde", self::serde::create(lua)?), ("stdio", stdio::create(lua)?), ("task", task::create(lua)?), ]; - // TODO: Remove this when we have proper LSP support for custom require types + // TODO: Remove this when we have proper LSP support for custom + // require types and no longer need to have builtins as globals let lua_globals = lua.globals(); - for (name, builtin) in &builtins { - lua_globals.set(*name, builtin.clone())?; + for name in BUILTINS_AS_GLOBALS { + let builtin = builtins.iter().find(|(gname, _)| gname == name).unwrap(); + lua_globals.set(*name, builtin.1.clone())?; } // Create our importer (require) with builtins diff --git a/packages/lib/src/globals/net.rs b/packages/lib/src/globals/net.rs index 7c524a1..6089e31 100644 --- a/packages/lib/src/globals/net.rs +++ b/packages/lib/src/globals/net.rs @@ -25,8 +25,6 @@ pub fn create(lua: &'static Lua) -> LuaResult { lua.set_named_registry_value("net.client", client)?; // Create the global table for net TableBuilder::new(lua)? - .with_function("encode", net_encode)? - .with_function("decode", net_decode)? .with_function("jsonEncode", net_json_encode)? .with_function("jsonDecode", net_json_decode)? .with_async_function("request", net_request)? @@ -43,22 +41,6 @@ fn create_user_agent_header() -> String { format!("{github_owner}-{github_repo}-cli") } -fn net_encode<'a>( - lua: &'static Lua, - (format, val, pretty): (EncodeDecodeFormat, LuaValue<'a>, Option), -) -> LuaResult> { - let config = EncodeDecodeConfig::from((format, pretty.unwrap_or_default())); - config.serialize_to_string(lua, val) -} - -fn net_decode<'a>( - lua: &'static Lua, - (format, str): (EncodeDecodeFormat, LuaString<'a>), -) -> LuaResult> { - let config = EncodeDecodeConfig::from(format); - config.deserialize_from_string(lua, str) -} - fn net_json_encode<'a>( lua: &'static Lua, (val, pretty): (LuaValue<'a>, Option), diff --git a/packages/lib/src/globals/serde.rs b/packages/lib/src/globals/serde.rs new file mode 100644 index 0000000..24674df --- /dev/null +++ b/packages/lib/src/globals/serde.rs @@ -0,0 +1,29 @@ +use mlua::prelude::*; + +use crate::lua::{ + net::{EncodeDecodeConfig, EncodeDecodeFormat}, + table::TableBuilder, +}; + +pub fn create(lua: &'static Lua) -> LuaResult { + TableBuilder::new(lua)? + .with_function("encode", serde_encode)? + .with_function("decode", serde_decode)? + .build_readonly() +} + +fn serde_encode<'a>( + lua: &'static Lua, + (format, val, pretty): (EncodeDecodeFormat, LuaValue<'a>, Option), +) -> LuaResult> { + let config = EncodeDecodeConfig::from((format, pretty.unwrap_or_default())); + config.serialize_to_string(lua, val) +} + +fn serde_decode<'a>( + lua: &'static Lua, + (format, str): (EncodeDecodeFormat, LuaString<'a>), +) -> LuaResult> { + let config = EncodeDecodeConfig::from(format); + config.deserialize_from_string(lua, str) +} diff --git a/packages/lib/src/tests.rs b/packages/lib/src/tests.rs index 48b401d..3738b7c 100644 --- a/packages/lib/src/tests.rs +++ b/packages/lib/src/tests.rs @@ -51,8 +51,6 @@ create_tests! { net_request_methods: "net/request/methods", net_request_query: "net/request/query", net_request_redirect: "net/request/redirect", - net_json_decode: "net/json/decode", - net_json_encode: "net/json/encode", net_serve_requests: "net/serve/requests", net_serve_websockets: "net/serve/websockets", process_args: "process/args", @@ -75,6 +73,10 @@ create_tests! { global_pcall: "globals/pcall", global_type: "globals/type", global_typeof: "globals/typeof", + serde_json_decode: "serde/json/decode", + serde_json_encode: "serde/json/encode", + serde_toml_decode: "serde/toml/decode", + serde_toml_encode: "serde/toml/encode", stdio_format: "stdio/format", stdio_color: "stdio/color", stdio_style: "stdio/style", diff --git a/tests/net/json/decode.luau b/tests/serde/json/decode.luau similarity index 100% rename from tests/net/json/decode.luau rename to tests/serde/json/decode.luau diff --git a/tests/net/json/encode.luau b/tests/serde/json/encode.luau similarity index 61% rename from tests/net/json/encode.luau rename to tests/serde/json/encode.luau index 19fa1fa..aa07142 100644 --- a/tests/net/json/encode.luau +++ b/tests/serde/json/encode.luau @@ -1,16 +1,7 @@ -local payload = [[{ - "Hello": "World", - "Inner": { - "Array": [ - 1, - 2, - 3 - ] - }, - "Foo": "Bar" -}]] +local serde = require("@lune/serde") :: any +local source = require("./source") -local decoded = net.jsonDecode(payload) +local decoded = serde.decode("json", source.pretty) assert(type(decoded) == "table", "Decoded payload was not a table") assert(decoded.Hello == "World", "Decoded payload Hello was not World") @@ -21,5 +12,8 @@ assert(type(decoded.Inner.Array[2]) == "number", "Decoded payload Inner.Array[2] assert(type(decoded.Inner.Array[3]) == "number", "Decoded payload Inner.Array[3] was not a number") assert(decoded.Foo == "Bar", "Decoded payload Foo was not Bar") -local encoded = net.jsonEncode(decoded, true) -assert(encoded == payload, "JSON round-trip did not produce the same result") +local encoded = serde.encode("json", decoded, false) +assert(encoded == source.encoded, "JSON round-trip did not produce the same result") + +local encodedPretty = serde.encode("json", decoded, true) +assert(encodedPretty == source.pretty, "JSON round-trip did not produce the same result (pretty)") diff --git a/tests/serde/json/source.luau b/tests/serde/json/source.luau new file mode 100644 index 0000000..0919cd0 --- /dev/null +++ b/tests/serde/json/source.luau @@ -0,0 +1,18 @@ +local JSON_STRING = [[{"Hello":"World","Inner":{"Array":[1,2,3]},"Foo":"Bar"}]] + +local JSON_STRING_PRETTY = [[{ + "Hello": "World", + "Inner": { + "Array": [ + 1, + 2, + 3 + ] + }, + "Foo": "Bar" +}]] + +return { + encoded = JSON_STRING, + pretty = JSON_STRING_PRETTY, +} diff --git a/tests/serde/toml/decode.luau b/tests/serde/toml/decode.luau new file mode 100644 index 0000000..674eeea --- /dev/null +++ b/tests/serde/toml/decode.luau @@ -0,0 +1,8 @@ +local serde = require("@lune/serde") :: any +local source = require("./source") + +local toml = serde.decode("toml", source.encoded) + +assert(toml.package.name == "my-cool-toml-package") +assert(toml.package.version == "0.1.0") +assert(toml.values.epic == true) diff --git a/tests/serde/toml/encode.luau b/tests/serde/toml/encode.luau new file mode 100644 index 0000000..986ae9b --- /dev/null +++ b/tests/serde/toml/encode.luau @@ -0,0 +1,5 @@ +local serde = require("@lune/serde") :: any +local source = require("./source") + +local str = serde.encode("toml", source.decoded) +assert(str == source.encoded) diff --git a/tests/serde/toml/source.luau b/tests/serde/toml/source.luau new file mode 100644 index 0000000..dd31e93 --- /dev/null +++ b/tests/serde/toml/source.luau @@ -0,0 +1,26 @@ +local TOML_LINES = { + "[package]", + 'name = "my-cool-toml-package"', + 'version = "0.1.0"', + "", + "[values]", + "epic = true", + "", +} + +local TOML_STRING = table.concat(TOML_LINES, "\n") + +local TOML_TABLE = { + package = { + name = "my-cool-toml-package", + version = "0.1.0", + }, + values = { + epic = true, + }, +} + +return { + encoded = TOML_STRING, + decoded = TOML_TABLE, +}