Skip to content

Commit

Permalink
Migrate roblox builtin to new lune-std-roblox crate
Browse files Browse the repository at this point in the history
  • Loading branch information
filiptibell committed Apr 22, 2024
1 parent 7f7cfb5 commit d0c15e9
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 4 deletions.
5 changes: 4 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions crates/lune-roblox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ rand = "0.8"
thiserror = "1.0"
once_cell = "1.17"

rbx_cookie = { version = "0.1.4", default-features = false }

rbx_binary = "0.7.3"
rbx_dom_weak = "2.6.0"
rbx_reflection = "4.4.0"
Expand Down
5 changes: 5 additions & 0 deletions crates/lune-std-roblox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,10 @@ workspace = true

[dependencies]
mlua = { version = "0.9.7", features = ["luau"] }
mlua-luau-scheduler = "0.0.1"

once_cell = "1.17"
rbx_cookie = { version = "0.1.4", default-features = false }

lune-utils = { version = "0.1.0", path = "../lune-utils" }
lune-roblox = { version = "0.1.0", path = "../lune-roblox" }
135 changes: 134 additions & 1 deletion crates/lune-std-roblox/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
#![allow(clippy::cargo_common_metadata)]

use mlua::prelude::*;
use mlua_luau_scheduler::LuaSpawnExt;
use once_cell::sync::OnceCell;

use lune_roblox::{
document::{Document, DocumentError, DocumentFormat, DocumentKind},
instance::{registry::InstanceRegistry, Instance},
reflection::Database as ReflectionDatabase,
};

static REFLECTION_DATABASE: OnceCell<ReflectionDatabase> = OnceCell::new();

use lune_utils::TableBuilder;

Expand All @@ -12,5 +22,128 @@ use lune_utils::TableBuilder;
Errors when out of memory.
*/
pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
TableBuilder::new(lua)?.build_readonly()
let mut roblox_constants = Vec::new();

let roblox_module = lune_roblox::module(lua)?;
for pair in roblox_module.pairs::<LuaValue, LuaValue>() {
roblox_constants.push(pair?);
}

TableBuilder::new(lua)?
.with_values(roblox_constants)?
.with_async_function("deserializePlace", deserialize_place)?
.with_async_function("deserializeModel", deserialize_model)?
.with_async_function("serializePlace", serialize_place)?
.with_async_function("serializeModel", serialize_model)?
.with_function("getAuthCookie", get_auth_cookie)?
.with_function("getReflectionDatabase", get_reflection_database)?
.with_function("implementProperty", implement_property)?
.with_function("implementMethod", implement_method)?
.build_readonly()
}

async fn deserialize_place<'lua>(
lua: &'lua Lua,
contents: LuaString<'lua>,
) -> LuaResult<LuaValue<'lua>> {
let bytes = contents.as_bytes().to_vec();
let fut = lua.spawn_blocking(move || {
let doc = Document::from_bytes(bytes, DocumentKind::Place)?;
let data_model = doc.into_data_model_instance()?;
Ok::<_, DocumentError>(data_model)
});
fut.await.into_lua_err()?.into_lua(lua)
}

async fn deserialize_model<'lua>(
lua: &'lua Lua,
contents: LuaString<'lua>,
) -> LuaResult<LuaValue<'lua>> {
let bytes = contents.as_bytes().to_vec();
let fut = lua.spawn_blocking(move || {
let doc = Document::from_bytes(bytes, DocumentKind::Model)?;
let instance_array = doc.into_instance_array()?;
Ok::<_, DocumentError>(instance_array)
});
fut.await.into_lua_err()?.into_lua(lua)
}

async fn serialize_place<'lua>(
lua: &'lua Lua,
(data_model, as_xml): (LuaUserDataRef<'lua, Instance>, Option<bool>),
) -> LuaResult<LuaString<'lua>> {
let data_model = (*data_model).clone();
let fut = lua.spawn_blocking(move || {
let doc = Document::from_data_model_instance(data_model)?;
let bytes = doc.to_bytes_with_format(match as_xml {
Some(true) => DocumentFormat::Xml,
_ => DocumentFormat::Binary,
})?;
Ok::<_, DocumentError>(bytes)
});
let bytes = fut.await.into_lua_err()?;
lua.create_string(bytes)
}

async fn serialize_model<'lua>(
lua: &'lua Lua,
(instances, as_xml): (Vec<LuaUserDataRef<'lua, Instance>>, Option<bool>),
) -> LuaResult<LuaString<'lua>> {
let instances = instances.iter().map(|i| (*i).clone()).collect();
let fut = lua.spawn_blocking(move || {
let doc = Document::from_instance_array(instances)?;
let bytes = doc.to_bytes_with_format(match as_xml {
Some(true) => DocumentFormat::Xml,
_ => DocumentFormat::Binary,
})?;
Ok::<_, DocumentError>(bytes)
});
let bytes = fut.await.into_lua_err()?;
lua.create_string(bytes)
}

fn get_auth_cookie(_: &Lua, raw: Option<bool>) -> LuaResult<Option<String>> {
if matches!(raw, Some(true)) {
Ok(rbx_cookie::get_value())
} else {
Ok(rbx_cookie::get())
}
}

fn get_reflection_database(_: &Lua, _: ()) -> LuaResult<ReflectionDatabase> {
Ok(*REFLECTION_DATABASE.get_or_init(ReflectionDatabase::new))
}

fn implement_property(
lua: &Lua,
(class_name, property_name, property_getter, property_setter): (
String,
String,
LuaFunction,
Option<LuaFunction>,
),
) -> LuaResult<()> {
let property_setter = if let Some(setter) = property_setter {
setter
} else {
let property_name = property_name.clone();
lua.create_function(move |_, _: LuaMultiValue| {
Err::<(), _>(LuaError::runtime(format!(
"Property '{property_name}' is read-only"
)))
})?
};
InstanceRegistry::insert_property_getter(lua, &class_name, &property_name, property_getter)
.into_lua_err()?;
InstanceRegistry::insert_property_setter(lua, &class_name, &property_name, property_setter)
.into_lua_err()?;
Ok(())
}

fn implement_method(
lua: &Lua,
(class_name, method_name, method): (String, String, LuaFunction),
) -> LuaResult<()> {
InstanceRegistry::insert_method(lua, &class_name, &method_name, method).into_lua_err()?;
Ok(())
}

0 comments on commit d0c15e9

Please sign in to comment.