From f22fe600c75f31c799b82a03ca9b681bf2241cdf Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Tue, 23 Aug 2022 00:40:13 -0700 Subject: [PATCH] Detailed error for swapping two arguments --- src/remodel_api/mod.rs | 55 +++++++++++++++++++- src/remodel_api/remodel.rs | 6 ++- test-scripts/write-place-model-old-order.lua | 15 ++++++ 3 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 test-scripts/write-place-model-old-order.lua diff --git a/src/remodel_api/mod.rs b/src/remodel_api/mod.rs index 7d7e0aa..c821574 100644 --- a/src/remodel_api/mod.rs +++ b/src/remodel_api/mod.rs @@ -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 { @@ -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 { + 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::()?; + + Ok(StringLuaInstanceBackCompat(( + filename.to_str()?.to_owned(), + instance, + ))) + } + + (Some(user_data_value @ LuaValue::UserData(user_data)), Some(LuaValue::String(_))) => { + if user_data.is::() { + 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.", + )), + } + } +} diff --git a/src/remodel_api/remodel.rs b/src/remodel_api/remodel.rs index 22c36fc..31c90ac 100644 --- a/src/remodel_api/remodel.rs +++ b/src/remodel_api/remodel.rs @@ -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) } @@ -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) { @@ -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) { diff --git a/test-scripts/write-place-model-old-order.lua b/test-scripts/write-place-model-old-order.lua new file mode 100644 index 0000000..68f6c07 --- /dev/null +++ b/test-scripts/write-place-model-old-order.lua @@ -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)