Use plain tables instead of userdata for globals

This commit is contained in:
Filip Tibell 2023-01-21 15:30:22 -05:00
parent d5b3d3f94b
commit e6faa3f6be
No known key found for this signature in database
7 changed files with 105 additions and 170 deletions

View file

@ -1,35 +1,22 @@
use mlua::{Lua, MultiValue, Result, UserData, UserDataMethods};
use mlua::{Lua, MultiValue, Result, Table};
use crate::utils::formatting::{
flush_stdout, pretty_format_multi_value, print_color, print_label, print_style,
};
pub struct Console();
impl Console {
pub fn new() -> Self {
Self()
}
}
impl Default for Console {
fn default() -> Self {
Self::new()
}
}
impl UserData for Console {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_function("resetColor", console_reset_color);
methods.add_function("setColor", console_set_color);
methods.add_function("resetStyle", console_reset_style);
methods.add_function("setStyle", console_set_style);
methods.add_function("format", console_format);
methods.add_function("log", console_log);
methods.add_function("info", console_info);
methods.add_function("warn", console_warn);
methods.add_function("error", console_error);
}
pub fn new(lua: &Lua) -> Result<Table> {
let tab = lua.create_table()?;
tab.raw_set("resetColor", lua.create_function(console_reset_color)?)?;
tab.raw_set("setColor", lua.create_function(console_set_color)?)?;
tab.raw_set("resetStyle", lua.create_function(console_reset_style)?)?;
tab.raw_set("setStyle", lua.create_function(console_set_style)?)?;
tab.raw_set("format", lua.create_function(console_format)?)?;
tab.raw_set("log", lua.create_function(console_log)?)?;
tab.raw_set("info", lua.create_function(console_info)?)?;
tab.raw_set("warn", lua.create_function(console_warn)?)?;
tab.raw_set("error", lua.create_function(console_error)?)?;
tab.set_readonly(true);
Ok(tab)
}
fn console_reset_color(_: &Lua, _: ()) -> Result<()> {

View file

@ -1,33 +1,20 @@
use std::path::{PathBuf, MAIN_SEPARATOR};
use mlua::{Lua, Result, UserData, UserDataMethods};
use mlua::{Lua, Result, Table};
use tokio::fs;
pub struct Fs();
impl Fs {
pub fn new() -> Self {
Self()
}
}
impl Default for Fs {
fn default() -> Self {
Self::new()
}
}
impl UserData for Fs {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_async_function("readFile", fs_read_file);
methods.add_async_function("readDir", fs_read_dir);
methods.add_async_function("writeFile", fs_write_file);
methods.add_async_function("writeDir", fs_write_dir);
methods.add_async_function("removeFile", fs_remove_file);
methods.add_async_function("removeDir", fs_remove_dir);
methods.add_async_function("isFile", fs_is_file);
methods.add_async_function("isDir", fs_is_dir);
}
pub fn new(lua: &Lua) -> Result<Table> {
let tab = lua.create_table()?;
tab.raw_set("readFile", lua.create_async_function(fs_read_file)?)?;
tab.raw_set("readDir", lua.create_async_function(fs_read_dir)?)?;
tab.raw_set("writeFile", lua.create_async_function(fs_write_file)?)?;
tab.raw_set("writeDir", lua.create_async_function(fs_write_dir)?)?;
tab.raw_set("removeFile", lua.create_async_function(fs_remove_file)?)?;
tab.raw_set("removeDir", lua.create_async_function(fs_remove_dir)?)?;
tab.raw_set("isFile", lua.create_async_function(fs_is_file)?)?;
tab.raw_set("isDir", lua.create_async_function(fs_is_dir)?)?;
tab.set_readonly(true);
Ok(tab)
}
async fn fs_read_file(_: &Lua, path: String) -> Result<String> {

View file

@ -4,8 +4,8 @@ mod net;
mod process;
mod task;
pub use console::Console as ConsoleGlobal;
pub use fs::Fs as FsGlobal;
pub use net::Net as NetGlobal;
pub use process::Process as ProcessGlobal;
pub use task::Task as TaskGlobal;
pub use console::new as new_console;
pub use fs::new as new_fs;
pub use net::new as new_net;
pub use process::new as new_process;
pub use task::new as new_task;

View file

@ -1,6 +1,6 @@
use std::{collections::HashMap, str::FromStr};
use mlua::{Error, Lua, LuaSerdeExt, Result, UserData, UserDataMethods, Value};
use mlua::{Error, Lua, LuaSerdeExt, Result, Table, Value};
use reqwest::{
header::{HeaderMap, HeaderName, HeaderValue},
Method,
@ -8,26 +8,13 @@ use reqwest::{
use crate::utils::net::get_request_user_agent_header;
pub struct Net();
impl Net {
pub fn new() -> Self {
Self()
}
}
impl Default for Net {
fn default() -> Self {
Self::new()
}
}
impl UserData for Net {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_function("jsonEncode", net_json_encode);
methods.add_function("jsonDecode", net_json_decode);
methods.add_async_function("request", net_request);
}
pub fn new(lua: &Lua) -> Result<Table> {
let tab = lua.create_table()?;
tab.raw_set("jsonEncode", lua.create_function(net_json_encode)?)?;
tab.raw_set("jsonDecode", lua.create_function(net_json_decode)?)?;
tab.raw_set("request", lua.create_async_function(net_request)?)?;
tab.set_readonly(true);
Ok(tab)
}
fn net_json_encode(_: &Lua, (val, pretty): (Value, Option<bool>)) -> Result<String> {

View file

@ -3,66 +3,44 @@ use std::{
process::{exit, Stdio},
};
use mlua::{
Error, Function, Lua, MetaMethod, Result, Table, UserData, UserDataFields, UserDataMethods,
Value,
};
use mlua::{Error, Function, Lua, MetaMethod, Result, Table, Value};
use os_str_bytes::RawOsString;
use tokio::process::Command;
pub struct Process {
args: Vec<String>,
pub fn new(lua: &Lua, args_vec: Vec<String>) -> Result<Table> {
// Create readonly args array
let inner_args = lua.create_table()?;
for arg in &args_vec {
inner_args.push(arg.clone())?;
}
impl Default for Process {
fn default() -> Self {
Self::new(vec![])
}
}
impl Process {
pub fn new(args: Vec<String>) -> Self {
Self { args }
}
}
impl UserData for Process {
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("args", |lua, this| {
// TODO: Use the same strategy as env uses below to avoid
// copying each time args are accessed? is it worth it?
let tab = lua.create_table()?;
for arg in &this.args {
tab.push(arg.clone())?;
}
tab.set_readonly(true);
Ok(tab)
});
fields.add_field_method_get("env", |lua, _| {
let meta = lua.create_table()?;
meta.raw_set(
inner_args.set_readonly(true);
// Create proxied env metatable that gets & sets real env vars
let inner_env_meta = lua.create_table()?;
inner_env_meta.raw_set(
MetaMethod::Index.name(),
lua.create_function(process_env_get)?,
)?;
meta.raw_set(
inner_env_meta.raw_set(
MetaMethod::NewIndex.name(),
lua.create_function(process_env_set)?,
)?;
meta.raw_set(
inner_env_meta.raw_set(
MetaMethod::Iter.name(),
lua.create_function(process_env_iter)?,
)?;
inner_env_meta.set_readonly(true);
// Create blank table for env with the metatable
let inner_env = lua.create_table()?;
inner_env.set_metatable(Some(inner_env_meta));
inner_env.set_readonly(true);
// Create the full process table
let tab = lua.create_table()?;
tab.set_metatable(Some(meta));
tab.raw_set("args", inner_args)?;
tab.raw_set("env", inner_env)?;
tab.raw_set("exit", lua.create_function(process_exit)?)?;
tab.raw_set("spawn", lua.create_async_function(process_spawn)?)?;
tab.set_readonly(true);
Ok(tab)
});
}
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_function("exit", process_exit);
methods.add_async_function("spawn", process_spawn);
}
}
fn process_env_get<'lua>(lua: &'lua Lua, (_, key): (Value<'lua>, String)) -> Result<Value<'lua>> {

View file

@ -1,36 +1,25 @@
use std::time::Duration;
use mlua::{Function, UserData, UserDataMethods, Value, Variadic};
use mlua::{Function, Lua, Result, Table, Value, Variadic};
use tokio::time;
const DEFAULT_SLEEP_DURATION: f32 = 1.0 / 60.0;
pub struct Task();
impl Task {
pub fn new() -> Self {
Self()
}
}
impl Default for Task {
fn default() -> Self {
Self::new()
}
}
impl UserData for Task {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_async_function(
pub fn new(lua: &Lua) -> Result<Table> {
let tab = lua.create_table()?;
tab.raw_set(
"defer",
lua.create_async_function(
|lua, (func, args): (Function, Variadic<Value>)| async move {
let thread = lua.create_thread(func)?;
thread.into_async(args).await?;
Ok(())
},
);
methods.add_async_function(
)?,
)?;
tab.raw_set(
"delay",
lua.create_async_function(
|lua, (func, duration, args): (Function, Option<f32>, Variadic<Value>)| async move {
let secs = duration.unwrap_or(DEFAULT_SLEEP_DURATION);
time::sleep(Duration::from_secs_f32(secs)).await;
@ -38,19 +27,26 @@ impl UserData for Task {
thread.into_async(args).await?;
Ok(())
},
);
methods.add_async_function(
)?,
)?;
tab.raw_set(
"spawn",
lua.create_async_function(
|lua, (func, args): (Function, Variadic<Value>)| async move {
let thread = lua.create_thread(func)?;
thread.into_async(args).await?;
Ok(())
},
);
methods.add_async_function("wait", |_, duration: Option<f32>| async move {
)?,
)?;
tab.raw_set(
"wait",
lua.create_async_function(|_, duration: Option<f32>| async move {
let secs = duration.unwrap_or(DEFAULT_SLEEP_DURATION);
time::sleep(Duration::from_secs_f32(secs)).await;
Ok(secs)
});
}
})?,
)?;
tab.set_readonly(true);
Ok(tab)
}

View file

@ -5,7 +5,7 @@ pub mod globals;
pub mod utils;
use crate::{
globals::{ConsoleGlobal, FsGlobal, NetGlobal, ProcessGlobal, TaskGlobal},
globals::{new_console, new_fs, new_net, new_process, new_task},
utils::formatting::{pretty_print_luau_error, print_label},
};
@ -29,11 +29,11 @@ impl Lune {
pub fn with_default_globals(self) -> Result<Self> {
{
let globals = self.lua.globals();
globals.raw_set("console", ConsoleGlobal::new())?;
globals.raw_set("fs", FsGlobal::new())?;
globals.raw_set("net", NetGlobal::new())?;
globals.raw_set("process", ProcessGlobal::new(self.args.clone()))?;
globals.raw_set("task", TaskGlobal::new())?;
globals.raw_set("console", new_console(&self.lua)?)?;
globals.raw_set("fs", new_fs(&self.lua)?)?;
globals.raw_set("net", new_net(&self.lua)?)?;
globals.raw_set("process", new_process(&self.lua, self.args.clone())?)?;
globals.raw_set("task", new_task(&self.lua)?)?;
globals.set_readonly(true);
}
Ok(self)