Improve error reporting & ergonomics for datatype conversion

This commit is contained in:
Filip Tibell 2023-03-11 20:50:53 +01:00
parent b1a3495a14
commit 7fd32e67c2
No known key found for this signature in database
7 changed files with 86 additions and 75 deletions

View file

@ -109,11 +109,12 @@ impl<'lua> LuaToRbxVariant<'lua> for LuaValue<'lua> {
*/ */
impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> { impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> {
#[rustfmt::skip]
fn rbx_variant_to_lua(lua: &'lua Lua, variant: &RbxVariant) -> DatatypeConversionResult<Self> { fn rbx_variant_to_lua(lua: &'lua Lua, variant: &RbxVariant) -> DatatypeConversionResult<Self> {
use super::types::*; use super::types::*;
use RbxVariant as Rbx; use RbxVariant as Rbx;
Ok(match variant { Ok(match variant.clone() {
// Not yet implemented datatypes // Not yet implemented datatypes
// Rbx::Axes(_) => todo!(), // Rbx::Axes(_) => todo!(),
// Rbx::BrickColor(_) => todo!(), // Rbx::BrickColor(_) => todo!(),
@ -131,18 +132,19 @@ impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> {
// Rbx::Rect(_) => todo!(), // Rbx::Rect(_) => todo!(),
// Rbx::Region3(_) => todo!(), // Rbx::Region3(_) => todo!(),
// Rbx::Region3int16(_) => todo!(), // Rbx::Region3int16(_) => todo!(),
Rbx::UDim(value) => lua.create_userdata(UDim::from(value))?,
Rbx::UDim(value) => lua.create_userdata(UDim::from(value))?,
Rbx::UDim2(value) => lua.create_userdata(UDim2::from(value))?, Rbx::UDim2(value) => lua.create_userdata(UDim2::from(value))?,
Rbx::Vector2(value) => lua.create_userdata(Vector2::from(value))?, Rbx::Vector2(value) => lua.create_userdata(Vector2::from(value))?,
Rbx::Vector2int16(value) => lua.create_userdata(Vector2int16::from(value))?, Rbx::Vector2int16(value) => lua.create_userdata(Vector2int16::from(value))?,
Rbx::Vector3(value) => lua.create_userdata(Vector3::from(value))?, Rbx::Vector3(value) => lua.create_userdata(Vector3::from(value))?,
Rbx::Vector3int16(value) => lua.create_userdata(Vector3int16::from(value))?, Rbx::Vector3int16(value) => lua.create_userdata(Vector3int16::from(value))?,
v => { v => {
return Err(DatatypeConversionError::FromRbxVariant { return Err(DatatypeConversionError::FromRbxVariant {
from: v.variant_name(), from: v.variant_name(),
to: "LuaValue", to: "userdata",
detail: Some("Type not supported".to_string()), detail: Some("Type not supported".to_string()),
}) })
} }
@ -151,31 +153,54 @@ impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> {
} }
impl<'lua> LuaToRbxVariant<'lua> for LuaAnyUserData<'lua> { impl<'lua> LuaToRbxVariant<'lua> for LuaAnyUserData<'lua> {
#[rustfmt::skip]
fn lua_to_rbx_variant( fn lua_to_rbx_variant(
&self, &self,
_: &'lua Lua, _: &'lua Lua,
variant_type: RbxVariantType, variant_type: RbxVariantType,
) -> DatatypeConversionResult<RbxVariant> { ) -> DatatypeConversionResult<RbxVariant> {
use super::types::*; use super::types::*;
use rbx_dom_weak::types as rbx;
Ok(if let Ok(value) = self.borrow::<UDim>() { let f = match variant_type {
RbxVariant::UDim((&*value).into()) RbxVariantType::UDim => convert::<UDim, rbx::UDim>,
} else if let Ok(value) = self.borrow::<UDim2>() { RbxVariantType::UDim2 => convert::<UDim2, rbx::UDim2>,
RbxVariant::UDim2((&*value).into())
} else if let Ok(value) = self.borrow::<Vector2>() { RbxVariantType::Vector2 => convert::<Vector2, rbx::Vector2>,
RbxVariant::Vector2((&*value).into()) RbxVariantType::Vector2int16 => convert::<Vector2int16, rbx::Vector2int16>,
} else if let Ok(value) = self.borrow::<Vector2int16>() { RbxVariantType::Vector3 => convert::<Vector3, rbx::Vector3>,
RbxVariant::Vector2int16((&*value).into()) RbxVariantType::Vector3int16 => convert::<Vector3int16, rbx::Vector3int16>,
} else if let Ok(value) = self.borrow::<Vector3>() {
RbxVariant::Vector3((&*value).into()) _ => return Err(DatatypeConversionError::ToRbxVariant {
} else if let Ok(value) = self.borrow::<Vector3int16>() {
RbxVariant::Vector3int16((&*value).into())
} else {
return Err(DatatypeConversionError::ToRbxVariant {
to: variant_type.variant_name(), to: variant_type.variant_name(),
from: "userdata", from: "userdata",
detail: None, detail: Some("Type not supported".to_string()),
}); }),
}) };
f(self, variant_type)
}
}
fn convert<Datatype, RbxType>(
userdata: &LuaAnyUserData,
variant_type: RbxVariantType,
) -> DatatypeConversionResult<RbxVariant>
where
Datatype: LuaUserData + Clone + 'static,
RbxType: From<Datatype> + Into<RbxVariant>,
{
match userdata.borrow::<Datatype>() {
Ok(value) => Ok(RbxType::from(value.clone()).into()),
Err(LuaError::UserDataTypeMismatch) => Err(DatatypeConversionError::ToRbxVariant {
to: variant_type.variant_name(),
from: "userdata",
detail: Some("Type mismatch".to_string()),
}),
Err(e) => Err(DatatypeConversionError::ToRbxVariant {
to: variant_type.variant_name(),
from: "userdata",
detail: Some(format!("Internal error: {e}")),
}),
} }
} }

View file

@ -18,6 +18,10 @@ pub struct UDim {
} }
impl UDim { impl UDim {
pub(super) fn new(scale: f32, offset: i32) -> Self {
Self { scale, offset }
}
pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> { pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
datatype_table.set( datatype_table.set(
"new", "new",
@ -91,8 +95,8 @@ impl ops::Sub for UDim {
} }
} }
impl From<&RbxUDim> for UDim { impl From<RbxUDim> for UDim {
fn from(v: &RbxUDim) -> Self { fn from(v: RbxUDim) -> Self {
UDim { UDim {
scale: v.scale, scale: v.scale,
offset: v.offset, offset: v.offset,
@ -100,8 +104,8 @@ impl From<&RbxUDim> for UDim {
} }
} }
impl From<&UDim> for RbxUDim { impl From<UDim> for RbxUDim {
fn from(v: &UDim) -> Self { fn from(v: UDim) -> Self {
RbxUDim { RbxUDim {
scale: v.scale, scale: v.scale,
offset: v.offset, offset: v.offset,

View file

@ -24,14 +24,8 @@ impl UDim2 {
"fromScale", "fromScale",
lua.create_function(|_, (x, y): (Option<f32>, Option<f32>)| { lua.create_function(|_, (x, y): (Option<f32>, Option<f32>)| {
Ok(UDim2 { Ok(UDim2 {
x: UDim { x: UDim::new(x.unwrap_or_default(), 0),
scale: x.unwrap_or_default(), y: UDim::new(y.unwrap_or_default(), 0),
offset: 0,
},
y: UDim {
scale: y.unwrap_or_default(),
offset: 0,
},
}) })
})?, })?,
)?; )?;
@ -39,14 +33,8 @@ impl UDim2 {
"fromOffset", "fromOffset",
lua.create_function(|_, (x, y): (Option<i32>, Option<i32>)| { lua.create_function(|_, (x, y): (Option<i32>, Option<i32>)| {
Ok(UDim2 { Ok(UDim2 {
x: UDim { x: UDim::new(0f32, x.unwrap_or_default()),
scale: 0f32, y: UDim::new(0f32, y.unwrap_or_default()),
offset: x.unwrap_or_default(),
},
y: UDim {
scale: 0f32,
offset: y.unwrap_or_default(),
},
}) })
})?, })?,
)?; )?;
@ -62,17 +50,11 @@ impl UDim2 {
}) })
} else if let Ok((sx, ox, sy, oy)) = ArgsNums::from_lua_multi(args, lua) { } else if let Ok((sx, ox, sy, oy)) = ArgsNums::from_lua_multi(args, lua) {
Ok(UDim2 { Ok(UDim2 {
x: UDim { x: UDim::new(sx.unwrap_or_default(), ox.unwrap_or_default()),
scale: sx.unwrap_or_default(), y: UDim::new(sy.unwrap_or_default(), oy.unwrap_or_default()),
offset: ox.unwrap_or_default(),
},
y: UDim {
scale: sy.unwrap_or_default(),
offset: oy.unwrap_or_default(),
},
}) })
} else { } else {
// TODO: Better error message here using arg types // FUTURE: Better error message here using given arg types
Err(LuaError::RuntimeError( Err(LuaError::RuntimeError(
"Invalid arguments to constructor".to_string(), "Invalid arguments to constructor".to_string(),
)) ))
@ -158,20 +140,20 @@ impl ops::Sub for UDim2 {
} }
} }
impl From<&RbxUDim2> for UDim2 { impl From<RbxUDim2> for UDim2 {
fn from(v: &RbxUDim2) -> Self { fn from(v: RbxUDim2) -> Self {
UDim2 { UDim2 {
x: (&v.x).into(), x: v.x.into(),
y: (&v.y).into(), y: v.y.into(),
} }
} }
} }
impl From<&UDim2> for RbxUDim2 { impl From<UDim2> for RbxUDim2 {
fn from(v: &UDim2) -> Self { fn from(v: UDim2) -> Self {
RbxUDim2 { RbxUDim2 {
x: (&v.x).into(), x: v.x.into(),
y: (&v.y).into(), y: v.y.into(),
} }
} }
} }

View file

@ -138,14 +138,14 @@ impl ops::Sub for Vector2 {
} }
} }
impl From<&RbxVector2> for Vector2 { impl From<RbxVector2> for Vector2 {
fn from(v: &RbxVector2) -> Self { fn from(v: RbxVector2) -> Self {
Vector2(Vec2 { x: v.x, y: v.y }) Vector2(Vec2 { x: v.x, y: v.y })
} }
} }
impl From<&Vector2> for RbxVector2 { impl From<Vector2> for RbxVector2 {
fn from(v: &Vector2) -> Self { fn from(v: Vector2) -> Self {
RbxVector2 { x: v.0.x, y: v.0.y } RbxVector2 { x: v.0.x, y: v.0.y }
} }
} }

View file

@ -113,8 +113,8 @@ impl ops::Sub for Vector2int16 {
} }
} }
impl From<&RbxVector2int16> for Vector2int16 { impl From<RbxVector2int16> for Vector2int16 {
fn from(v: &RbxVector2int16) -> Self { fn from(v: RbxVector2int16) -> Self {
Vector2int16(IVec2 { Vector2int16(IVec2 {
x: v.x.clamp(i16::MIN, i16::MAX) as i32, x: v.x.clamp(i16::MIN, i16::MAX) as i32,
y: v.y.clamp(i16::MIN, i16::MAX) as i32, y: v.y.clamp(i16::MIN, i16::MAX) as i32,
@ -122,8 +122,8 @@ impl From<&RbxVector2int16> for Vector2int16 {
} }
} }
impl From<&Vector2int16> for RbxVector2int16 { impl From<Vector2int16> for RbxVector2int16 {
fn from(v: &Vector2int16) -> Self { fn from(v: Vector2int16) -> Self {
RbxVector2int16 { RbxVector2int16 {
x: v.0.x.clamp(i16::MIN as i32, i16::MAX as i32) as i16, x: v.0.x.clamp(i16::MIN as i32, i16::MAX as i32) as i16,
y: v.0.y.clamp(i16::MIN as i32, i16::MAX as i32) as i16, y: v.0.y.clamp(i16::MIN as i32, i16::MAX as i32) as i16,

View file

@ -152,8 +152,8 @@ impl ops::Sub for Vector3 {
} }
} }
impl From<&RbxVector3> for Vector3 { impl From<RbxVector3> for Vector3 {
fn from(v: &RbxVector3) -> Self { fn from(v: RbxVector3) -> Self {
Vector3(Vec3 { Vector3(Vec3 {
x: v.x, x: v.x,
y: v.y, y: v.y,
@ -162,8 +162,8 @@ impl From<&RbxVector3> for Vector3 {
} }
} }
impl From<&Vector3> for RbxVector3 { impl From<Vector3> for RbxVector3 {
fn from(v: &Vector3) -> Self { fn from(v: Vector3) -> Self {
RbxVector3 { RbxVector3 {
x: v.0.x, x: v.0.x,
y: v.0.y, y: v.0.y,

View file

@ -115,8 +115,8 @@ impl ops::Sub for Vector3int16 {
} }
} }
impl From<&RbxVector3int16> for Vector3int16 { impl From<RbxVector3int16> for Vector3int16 {
fn from(v: &RbxVector3int16) -> Self { fn from(v: RbxVector3int16) -> Self {
Vector3int16(IVec3 { Vector3int16(IVec3 {
x: v.x.clamp(i16::MIN, i16::MAX) as i32, x: v.x.clamp(i16::MIN, i16::MAX) as i32,
y: v.y.clamp(i16::MIN, i16::MAX) as i32, y: v.y.clamp(i16::MIN, i16::MAX) as i32,
@ -125,8 +125,8 @@ impl From<&RbxVector3int16> for Vector3int16 {
} }
} }
impl From<&Vector3int16> for RbxVector3int16 { impl From<Vector3int16> for RbxVector3int16 {
fn from(v: &Vector3int16) -> Self { fn from(v: Vector3int16) -> Self {
RbxVector3int16 { RbxVector3int16 {
x: v.0.x.clamp(i16::MIN as i32, i16::MAX as i32) as i16, x: v.0.x.clamp(i16::MIN as i32, i16::MAX as i32) as i16,
y: v.0.y.clamp(i16::MIN as i32, i16::MAX as i32) as i16, y: v.0.y.clamp(i16::MIN as i32, i16::MAX as i32) as i16,