mirror of
https://github.com/lune-org/lune.git
synced 2024-12-12 04:50:36 +00:00
Move net encode/decode into serde builtin instead
This commit is contained in:
parent
1f887cef07
commit
9e6cd4b0af
12 changed files with 128 additions and 54 deletions
11
CHANGELOG.md
11
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")` ... <br />
|
||||
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. <br />
|
||||
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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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<String>) -> 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
|
||||
|
|
|
@ -25,8 +25,6 @@ pub fn create(lua: &'static Lua) -> LuaResult<LuaTable> {
|
|||
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<bool>),
|
||||
) -> LuaResult<LuaString<'a>> {
|
||||
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<LuaValue<'a>> {
|
||||
let config = EncodeDecodeConfig::from(format);
|
||||
config.deserialize_from_string(lua, str)
|
||||
}
|
||||
|
||||
fn net_json_encode<'a>(
|
||||
lua: &'static Lua,
|
||||
(val, pretty): (LuaValue<'a>, Option<bool>),
|
||||
|
|
29
packages/lib/src/globals/serde.rs
Normal file
29
packages/lib/src/globals/serde.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
use mlua::prelude::*;
|
||||
|
||||
use crate::lua::{
|
||||
net::{EncodeDecodeConfig, EncodeDecodeFormat},
|
||||
table::TableBuilder,
|
||||
};
|
||||
|
||||
pub fn create(lua: &'static Lua) -> LuaResult<LuaTable> {
|
||||
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<bool>),
|
||||
) -> LuaResult<LuaString<'a>> {
|
||||
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<LuaValue<'a>> {
|
||||
let config = EncodeDecodeConfig::from(format);
|
||||
config.deserialize_from_string(lua, str)
|
||||
}
|
|
@ -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",
|
||||
|
|
|
@ -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)")
|
18
tests/serde/json/source.luau
Normal file
18
tests/serde/json/source.luau
Normal file
|
@ -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,
|
||||
}
|
8
tests/serde/toml/decode.luau
Normal file
8
tests/serde/toml/decode.luau
Normal file
|
@ -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)
|
5
tests/serde/toml/encode.luau
Normal file
5
tests/serde/toml/encode.luau
Normal file
|
@ -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)
|
26
tests/serde/toml/source.luau
Normal file
26
tests/serde/toml/source.luau
Normal file
|
@ -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,
|
||||
}
|
Loading…
Reference in a new issue