Skip to content
This repository has been archived by the owner on Jul 22, 2023. It is now read-only.

Add detailed error for swapping two arguments #85

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion src/remodel_api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
mod json;
mod remodel;

use mlua::Lua;
use mlua::{FromLuaMulti, Lua, Value as LuaValue};

pub use json::Json;
pub use remodel::Remodel;

use crate::roblox_api::LuaInstance;

pub struct RemodelApi;

impl RemodelApi {
Expand All @@ -16,3 +18,54 @@ impl RemodelApi {
Ok(())
}
}

/// Takes (String, LuaInstance) as a variadic, but reports a useful error
/// if the arguments are swapped.
pub struct StringLuaInstanceBackCompat(pub (String, LuaInstance));

impl<'lua> FromLuaMulti<'lua> for StringLuaInstanceBackCompat {
fn from_lua_multi(values: mlua::MultiValue<'lua>, _lua: &'lua Lua) -> mlua::Result<Self> {
let values = values.into_vec();

match (values.get(0), values.get(1)) {
(Some(LuaValue::String(filename)), Some(LuaValue::UserData(user_data))) => {
let instance = user_data.take::<LuaInstance>()?;

Ok(StringLuaInstanceBackCompat((
filename.to_str()?.to_owned(),
instance,
)))
}

(Some(user_data_value @ LuaValue::UserData(user_data)), Some(LuaValue::String(_))) => {
if user_data.is::<LuaInstance>() {
Err(mlua::Error::external("The two arguments are swapped. The first argument should be the filename, and the second argument should be the instance."))
} else {
Err(mlua::Error::external(format!(
"Expected two arguments, a filename and an Instance. received string and {}.",
user_data_value.type_name()
)))
}
}

(Some(one), Some(two)) => Err(mlua::Error::external(format!(
"Expected two arguments, a filename and an Instance. received {} and {}.",
one.type_name(),
two.type_name()
))),

(Some(one), None) => Err(mlua::Error::external(format!(
"Expected two arguments, a filename and an Instance. only received {}.",
one.type_name()
))),

(None, Some(_)) => {
unreachable!("the first value of the MultiValue was None, but the second was Some")
}

(None, None) => Err(mlua::Error::external(
"Expected two arguments, a filename and an Instance.",
)),
}
}
}
6 changes: 4 additions & 2 deletions src/remodel_api/remodel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use crate::{
value::{lua_to_rbxvalue, rbxvalue_to_lua, type_from_str},
};

use super::StringLuaInstanceBackCompat;

fn xml_encode_options() -> rbx_xml::EncodeOptions {
rbx_xml::EncodeOptions::new().property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown)
}
Expand Down Expand Up @@ -495,7 +497,7 @@ impl UserData for Remodel {

methods.add_function(
"writePlaceFile",
|_context, (lua_path, instance): (String, LuaInstance)| {
|_context, StringLuaInstanceBackCompat((lua_path, instance)): StringLuaInstanceBackCompat| {
let path = Path::new(&lua_path);

match path.extension().and_then(OsStr::to_str) {
Expand All @@ -511,7 +513,7 @@ impl UserData for Remodel {

methods.add_function(
"writeModelFile",
|_context, (lua_path, instance): (String, LuaInstance)| {
|_context, StringLuaInstanceBackCompat((lua_path, instance)): StringLuaInstanceBackCompat| {
let path = Path::new(&lua_path);

match path.extension().and_then(OsStr::to_str) {
Expand Down
15 changes: 15 additions & 0 deletions test-scripts/write-place-model-old-order.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
local game = remodel.readPlaceFile("test-models/place-with-models.rbxlx")

local success, problem = pcall(function()
remodel.writePlaceFile(game, "temp/new-place.rbxlx")
end)

assert(not success)
assert(tostring(problem):match("The two arguments are swapped") ~= nil)

success, problem = pcall(function()
remodel.writeModelFile(game, "temp/new-model.rbxmx")
end)

assert(not success)
assert(tostring(problem):match("The two arguments are swapped") ~= nil)