mirror of
https://github.com/lune-org/lune.git
synced 2024-12-13 13:30:38 +00:00
Implement translation layer between lua values and rbx_dom_weak variants
This commit is contained in:
parent
a31553e130
commit
078c08eabf
3 changed files with 187 additions and 3 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -861,6 +861,7 @@ dependencies = [
|
||||||
name = "lune-roblox"
|
name = "lune-roblox"
|
||||||
version = "0.5.5"
|
version = "0.5.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"base64 0.21.0",
|
||||||
"glam",
|
"glam",
|
||||||
"mlua",
|
"mlua",
|
||||||
"rbx_binary",
|
"rbx_binary",
|
||||||
|
|
|
@ -17,6 +17,7 @@ path = "src/lib.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
mlua.workspace = true
|
mlua.workspace = true
|
||||||
|
|
||||||
|
base64 = "0.21"
|
||||||
glam = "0.23"
|
glam = "0.23"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ pub mod types {
|
||||||
pub use super::vector3::Vector3;
|
pub use super::vector3::Vector3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trait definitions for conversion between rbx_dom_weak variant <-> datatype
|
// Trait definitions for conversion between rbx_dom_weak variant <-> our custom datatypes
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) enum RbxConversionError {
|
pub(crate) enum RbxConversionError {
|
||||||
|
@ -30,6 +30,17 @@ pub(crate) enum RbxConversionError {
|
||||||
can_convert_to: Option<&'static str>,
|
can_convert_to: Option<&'static str>,
|
||||||
detail: Option<String>,
|
detail: Option<String>,
|
||||||
},
|
},
|
||||||
|
External {
|
||||||
|
message: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RbxConversionError {
|
||||||
|
pub fn external(e: impl std::error::Error) -> Self {
|
||||||
|
RbxConversionError::External {
|
||||||
|
message: e.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) type RbxConversionResult<T> = Result<T, RbxConversionError>;
|
pub(crate) type RbxConversionResult<T> = Result<T, RbxConversionError>;
|
||||||
|
@ -49,7 +60,7 @@ pub(crate) trait DatatypeTable {
|
||||||
fn make_dt_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()>;
|
fn make_dt_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shared impls for datatype metamethods
|
// Shared impls for datatype metamethods belonging to this module
|
||||||
|
|
||||||
fn datatype_impl_to_string<D>(_: &Lua, datatype: &D, _: ()) -> LuaResult<String>
|
fn datatype_impl_to_string<D>(_: &Lua, datatype: &D, _: ()) -> LuaResult<String>
|
||||||
where
|
where
|
||||||
|
@ -128,6 +139,177 @@ impl RbxVariantDisplayName for RbxVariant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generic impls for converting from lua values <-> rbx_dom_weak variants
|
||||||
|
// We use a separate trait here since creating lua stuff needs the lua context
|
||||||
|
|
||||||
|
pub(crate) trait FromRbxVariantLua<'lua>: Sized {
|
||||||
|
fn from_rbx_variant_lua(variant: &RbxVariant, lua: &'lua Lua) -> RbxConversionResult<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'lua> FromRbxVariantLua<'lua> for LuaValue<'lua> {
|
||||||
|
fn from_rbx_variant_lua(variant: &RbxVariant, lua: &'lua Lua) -> RbxConversionResult<Self> {
|
||||||
|
use self::types::*;
|
||||||
|
use base64::engine::general_purpose::STANDARD_NO_PAD;
|
||||||
|
use base64::engine::Engine as _;
|
||||||
|
use RbxVariant as Rbx;
|
||||||
|
|
||||||
|
match variant {
|
||||||
|
// Primitives
|
||||||
|
Rbx::Bool(b) => Ok(LuaValue::Boolean(*b)),
|
||||||
|
Rbx::Int64(i) => Ok(LuaValue::Integer(*i as i32)),
|
||||||
|
Rbx::Int32(i) => Ok(LuaValue::Integer(*i)),
|
||||||
|
Rbx::Float64(n) => Ok(LuaValue::Number(*n)),
|
||||||
|
Rbx::Float32(n) => Ok(LuaValue::Number(*n as f64)),
|
||||||
|
Rbx::String(s) => Ok(LuaValue::String(
|
||||||
|
lua.create_string(s).map_err(RbxConversionError::external)?,
|
||||||
|
)),
|
||||||
|
Rbx::Content(s) => Ok(LuaValue::String(
|
||||||
|
lua.create_string(AsRef::<str>::as_ref(s))
|
||||||
|
.map_err(RbxConversionError::external)?,
|
||||||
|
)),
|
||||||
|
Rbx::BinaryString(s) => {
|
||||||
|
let encoded = STANDARD_NO_PAD.encode(AsRef::<[u8]>::as_ref(s));
|
||||||
|
Ok(LuaValue::String(
|
||||||
|
lua.create_string(&encoded)
|
||||||
|
.map_err(RbxConversionError::external)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
// Custom datatypes
|
||||||
|
// NOTE: When adding a new datatype, also add it in the FromRbxVariantLua impl below
|
||||||
|
Rbx::Vector2(_) => Vector2::from_rbx_variant(variant)?
|
||||||
|
.to_lua(lua)
|
||||||
|
.map_err(RbxConversionError::external),
|
||||||
|
Rbx::Vector3(_) => Vector3::from_rbx_variant(variant)?
|
||||||
|
.to_lua(lua)
|
||||||
|
.map_err(RbxConversionError::external),
|
||||||
|
// Not yet implemented datatypes
|
||||||
|
Rbx::Axes(_) => todo!(),
|
||||||
|
Rbx::BrickColor(_) => todo!(),
|
||||||
|
Rbx::CFrame(_) => todo!(),
|
||||||
|
Rbx::Color3(_) => todo!(),
|
||||||
|
Rbx::Color3uint8(_) => todo!(),
|
||||||
|
Rbx::ColorSequence(_) => todo!(),
|
||||||
|
Rbx::Enum(_) => todo!(),
|
||||||
|
Rbx::Faces(_) => todo!(),
|
||||||
|
Rbx::NumberRange(_) => todo!(),
|
||||||
|
Rbx::NumberSequence(_) => todo!(),
|
||||||
|
Rbx::OptionalCFrame(_) => todo!(),
|
||||||
|
Rbx::PhysicalProperties(_) => todo!(),
|
||||||
|
Rbx::Ray(_) => todo!(),
|
||||||
|
Rbx::Rect(_) => todo!(),
|
||||||
|
Rbx::Region3(_) => todo!(),
|
||||||
|
Rbx::Region3int16(_) => todo!(),
|
||||||
|
Rbx::UDim(_) => todo!(),
|
||||||
|
Rbx::UDim2(_) => todo!(),
|
||||||
|
Rbx::Vector2int16(_) => todo!(),
|
||||||
|
Rbx::Vector3int16(_) => todo!(),
|
||||||
|
v => Err(RbxConversionError::FromRbxVariant {
|
||||||
|
from: v.display_name(),
|
||||||
|
to: "LuaValue",
|
||||||
|
detail: Some("Type not supported".to_string()),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'lua> ToRbxVariant for LuaValue<'lua> {
|
||||||
|
fn to_rbx_variant(
|
||||||
|
&self,
|
||||||
|
desired_type: Option<RbxVariantType>,
|
||||||
|
) -> RbxConversionResult<RbxVariant> {
|
||||||
|
use self::types::*;
|
||||||
|
use base64::engine::general_purpose::STANDARD_NO_PAD;
|
||||||
|
use base64::engine::Engine as _;
|
||||||
|
use RbxVariantType as Rbx;
|
||||||
|
|
||||||
|
if let Some(desired_type) = desired_type {
|
||||||
|
match (self, desired_type) {
|
||||||
|
// Primitives
|
||||||
|
(LuaValue::Boolean(b), Rbx::Bool) => Ok(RbxVariant::Bool(*b)),
|
||||||
|
(LuaValue::Integer(i), Rbx::Int64) => Ok(RbxVariant::Int64(*i as i64)),
|
||||||
|
(LuaValue::Integer(i), Rbx::Int32) => Ok(RbxVariant::Int32(*i)),
|
||||||
|
(LuaValue::Integer(i), Rbx::Float64) => Ok(RbxVariant::Float64(*i as f64)),
|
||||||
|
(LuaValue::Integer(i), Rbx::Float32) => Ok(RbxVariant::Float32(*i as f32)),
|
||||||
|
(LuaValue::Number(n), Rbx::Int64) => Ok(RbxVariant::Int64(*n as i64)),
|
||||||
|
(LuaValue::Number(n), Rbx::Int32) => Ok(RbxVariant::Int32(*n as i32)),
|
||||||
|
(LuaValue::Number(n), Rbx::Float64) => Ok(RbxVariant::Float64(*n)),
|
||||||
|
(LuaValue::Number(n), Rbx::Float32) => Ok(RbxVariant::Float32(*n as f32)),
|
||||||
|
(LuaValue::String(s), Rbx::String) => Ok(RbxVariant::String(
|
||||||
|
s.to_str()
|
||||||
|
.map_err(RbxConversionError::external)?
|
||||||
|
.to_string(),
|
||||||
|
)),
|
||||||
|
(LuaValue::String(s), Rbx::Content) => Ok(RbxVariant::Content(
|
||||||
|
s.to_str()
|
||||||
|
.map_err(RbxConversionError::external)?
|
||||||
|
.to_string()
|
||||||
|
.into(),
|
||||||
|
)),
|
||||||
|
(LuaValue::String(s), Rbx::BinaryString) => Ok(RbxVariant::BinaryString(
|
||||||
|
STANDARD_NO_PAD
|
||||||
|
.decode(s)
|
||||||
|
.map_err(RbxConversionError::external)?
|
||||||
|
.into(),
|
||||||
|
)),
|
||||||
|
// Custom datatypes
|
||||||
|
// NOTE: When adding a new datatype, also add it below + in the FromRbxVariantLua impl above
|
||||||
|
(LuaValue::UserData(u), d) => {
|
||||||
|
if let Ok(v2) = u.borrow::<Vector2>() {
|
||||||
|
v2.to_rbx_variant(Some(d))
|
||||||
|
} else if let Ok(v3) = u.borrow::<Vector3>() {
|
||||||
|
v3.to_rbx_variant(Some(d))
|
||||||
|
} else {
|
||||||
|
Err(RbxConversionError::ToRbxVariant {
|
||||||
|
to: d.display_name(),
|
||||||
|
from: "userdata",
|
||||||
|
detail: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Not yet implemented rbx types
|
||||||
|
(v, d) => Err(RbxConversionError::ToRbxVariant {
|
||||||
|
to: d.display_name(),
|
||||||
|
from: v.type_name(),
|
||||||
|
detail: None,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match self {
|
||||||
|
// Primitives
|
||||||
|
LuaValue::Boolean(b) => Ok(RbxVariant::Bool(*b)),
|
||||||
|
LuaValue::Integer(i) => Ok(RbxVariant::Int32(*i)),
|
||||||
|
LuaValue::Number(n) => Ok(RbxVariant::Float64(*n)),
|
||||||
|
LuaValue::String(s) => Ok(RbxVariant::String(
|
||||||
|
s.to_str()
|
||||||
|
.map_err(RbxConversionError::external)?
|
||||||
|
.to_string(),
|
||||||
|
)),
|
||||||
|
// Custom datatypes
|
||||||
|
// NOTE: When adding a new datatype, also add it above
|
||||||
|
LuaValue::UserData(u) => {
|
||||||
|
if let Ok(v2) = u.borrow::<Vector2>() {
|
||||||
|
v2.to_rbx_variant(None)
|
||||||
|
} else if let Ok(v3) = u.borrow::<Vector3>() {
|
||||||
|
v3.to_rbx_variant(None)
|
||||||
|
} else {
|
||||||
|
Err(RbxConversionError::ToRbxVariant {
|
||||||
|
to: "Variant",
|
||||||
|
from: "userdata",
|
||||||
|
detail: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Not yet implemented rbx types
|
||||||
|
v => Err(RbxConversionError::ToRbxVariant {
|
||||||
|
to: "Variant",
|
||||||
|
from: v.type_name(),
|
||||||
|
detail: None,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Implement tests for all datatypes in lua and run them here
|
// TODO: Implement tests for all datatypes in lua and run them here
|
||||||
// using the same mechanic we have to run tests in the main lib, these
|
// using the same mechanic we use to run tests in the main lib, these
|
||||||
// tests should also live next to other folders like fs, net, task, ..
|
// tests should also live next to other folders like fs, net, task, ..
|
||||||
|
|
Loading…
Reference in a new issue