mirror of
https://github.com/CompeyDev/lune-packaging.git
synced 2025-01-09 20:29:10 +00:00
Roblox datatypes refactor & organization
This commit is contained in:
parent
4afb51830c
commit
0f9caf5461
11 changed files with 470 additions and 440 deletions
190
packages/lib-roblox/src/datatypes/conversion.rs
Normal file
190
packages/lib-roblox/src/datatypes/conversion.rs
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
use rbx_dom_weak::types::{Variant as RbxVariant, VariantType as RbxVariantType};
|
||||||
|
|
||||||
|
use crate::datatypes::extension::RbxVariantExt;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub(crate) trait ToRbxVariant {
|
||||||
|
fn to_rbx_variant(
|
||||||
|
&self,
|
||||||
|
desired_type: Option<RbxVariantType>,
|
||||||
|
) -> DatatypeConversionResult<RbxVariant>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait FromRbxVariant: Sized {
|
||||||
|
fn from_rbx_variant(variant: &RbxVariant) -> DatatypeConversionResult<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait FromRbxVariantLua<'lua>: Sized {
|
||||||
|
fn from_rbx_variant_lua(variant: &RbxVariant, lua: &'lua Lua)
|
||||||
|
-> DatatypeConversionResult<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Blanket trait implementations for converting between LuaValue and rbx_dom Variant values
|
||||||
|
|
||||||
|
These should be considered stable and one, already containing all of the primitive types
|
||||||
|
|
||||||
|
See bottom of module for implementations between our custom datatypes and lua userdata
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
impl<'lua> FromRbxVariantLua<'lua> for LuaValue<'lua> {
|
||||||
|
fn from_rbx_variant_lua(
|
||||||
|
variant: &RbxVariant,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
) -> DatatypeConversionResult<Self> {
|
||||||
|
use base64::engine::general_purpose::STANDARD_NO_PAD;
|
||||||
|
use base64::engine::Engine as _;
|
||||||
|
use RbxVariant as Rbx;
|
||||||
|
|
||||||
|
match LuaAnyUserData::from_rbx_variant_lua(variant, lua) {
|
||||||
|
Ok(value) => Ok(LuaValue::UserData(value)),
|
||||||
|
Err(e) => match variant {
|
||||||
|
Rbx::Bool(b) => Ok(LuaValue::Boolean(*b)),
|
||||||
|
Rbx::Int64(i) => Ok(LuaValue::Number(*i as f64)),
|
||||||
|
Rbx::Int32(i) => Ok(LuaValue::Number(*i as f64)),
|
||||||
|
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)?)),
|
||||||
|
Rbx::Content(s) => Ok(LuaValue::String(
|
||||||
|
lua.create_string(AsRef::<str>::as_ref(s))?,
|
||||||
|
)),
|
||||||
|
Rbx::BinaryString(s) => {
|
||||||
|
let encoded = STANDARD_NO_PAD.encode(AsRef::<[u8]>::as_ref(s));
|
||||||
|
Ok(LuaValue::String(lua.create_string(&encoded)?))
|
||||||
|
}
|
||||||
|
_ => Err(e),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'lua> ToRbxVariant for LuaValue<'lua> {
|
||||||
|
fn to_rbx_variant(
|
||||||
|
&self,
|
||||||
|
desired_type: Option<RbxVariantType>,
|
||||||
|
) -> DatatypeConversionResult<RbxVariant> {
|
||||||
|
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) {
|
||||||
|
(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()?.to_string()))
|
||||||
|
}
|
||||||
|
(LuaValue::String(s), Rbx::Content) => {
|
||||||
|
Ok(RbxVariant::Content(s.to_str()?.to_string().into()))
|
||||||
|
}
|
||||||
|
(LuaValue::String(s), Rbx::BinaryString) => {
|
||||||
|
Ok(RbxVariant::BinaryString(STANDARD_NO_PAD.decode(s)?.into()))
|
||||||
|
}
|
||||||
|
(LuaValue::UserData(u), d) => u.to_rbx_variant(Some(d)),
|
||||||
|
(v, d) => Err(DatatypeConversionError::ToRbxVariant {
|
||||||
|
to: d.variant_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()?.to_string())),
|
||||||
|
LuaValue::UserData(u) => u.to_rbx_variant(None),
|
||||||
|
v => Err(DatatypeConversionError::ToRbxVariant {
|
||||||
|
to: "Variant",
|
||||||
|
from: v.type_name(),
|
||||||
|
detail: None,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Trait implementations for converting between all of
|
||||||
|
our custom datatypes and generic Lua userdata values
|
||||||
|
|
||||||
|
NOTE: When adding a new datatype, make sure to add it below to _both_
|
||||||
|
of the traits and not just one to allow for bidirectional conversion
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
impl<'lua> FromRbxVariantLua<'lua> for LuaAnyUserData<'lua> {
|
||||||
|
#[rustfmt::skip]
|
||||||
|
fn from_rbx_variant_lua(variant: &RbxVariant, lua: &'lua Lua) -> DatatypeConversionResult<Self> {
|
||||||
|
use RbxVariant as Rbx;
|
||||||
|
use super::types::*;
|
||||||
|
match variant {
|
||||||
|
Rbx::Vector2(_) => Ok(lua.create_userdata(Vector2::from_rbx_variant(variant)?)?),
|
||||||
|
Rbx::Vector2int16(_) => Ok(lua.create_userdata(Vector2int16::from_rbx_variant(variant)?)?),
|
||||||
|
Rbx::Vector3(_) => Ok(lua.create_userdata(Vector3::from_rbx_variant(variant)?)?),
|
||||||
|
Rbx::Vector3int16(_) => Ok(lua.create_userdata(Vector3int16::from_rbx_variant(variant)?)?),
|
||||||
|
// 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!(),
|
||||||
|
v => Err(DatatypeConversionError::FromRbxVariant {
|
||||||
|
from: v.variant_name(),
|
||||||
|
to: "LuaValue",
|
||||||
|
detail: Some("Type not supported".to_string()),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'lua> ToRbxVariant for LuaAnyUserData<'lua> {
|
||||||
|
fn to_rbx_variant(
|
||||||
|
&self,
|
||||||
|
desired_type: Option<RbxVariantType>,
|
||||||
|
) -> DatatypeConversionResult<RbxVariant> {
|
||||||
|
use super::types::*;
|
||||||
|
if let Ok(v2) = self.borrow::<Vector2>() {
|
||||||
|
v2.to_rbx_variant(desired_type)
|
||||||
|
} else if let Ok(v2i) = self.borrow::<Vector2int16>() {
|
||||||
|
v2i.to_rbx_variant(desired_type)
|
||||||
|
} else if let Ok(v3) = self.borrow::<Vector3>() {
|
||||||
|
v3.to_rbx_variant(desired_type)
|
||||||
|
} else if let Ok(v3i) = self.borrow::<Vector3int16>() {
|
||||||
|
v3i.to_rbx_variant(desired_type)
|
||||||
|
} else {
|
||||||
|
Err(DatatypeConversionError::ToRbxVariant {
|
||||||
|
to: desired_type.map(|d| d.variant_name()).unwrap_or("Variant"),
|
||||||
|
from: "userdata",
|
||||||
|
detail: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
packages/lib-roblox/src/datatypes/extension.rs
Normal file
52
packages/lib-roblox/src/datatypes/extension.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub(super) trait RbxVariantExt {
|
||||||
|
fn variant_name(&self) -> &'static str;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RbxVariantExt for RbxVariantType {
|
||||||
|
fn variant_name(&self) -> &'static str {
|
||||||
|
use RbxVariantType::*;
|
||||||
|
match self {
|
||||||
|
Axes => "Axes",
|
||||||
|
BinaryString => "BinaryString",
|
||||||
|
Bool => "Bool",
|
||||||
|
BrickColor => "BrickColor",
|
||||||
|
CFrame => "CFrame",
|
||||||
|
Color3 => "Color3",
|
||||||
|
Color3uint8 => "Color3uint8",
|
||||||
|
ColorSequence => "ColorSequence",
|
||||||
|
Content => "Content",
|
||||||
|
Enum => "Enum",
|
||||||
|
Faces => "Faces",
|
||||||
|
Float32 => "Float32",
|
||||||
|
Float64 => "Float64",
|
||||||
|
Int32 => "Int32",
|
||||||
|
Int64 => "Int64",
|
||||||
|
NumberRange => "NumberRange",
|
||||||
|
NumberSequence => "NumberSequence",
|
||||||
|
PhysicalProperties => "PhysicalProperties",
|
||||||
|
Ray => "Ray",
|
||||||
|
Rect => "Rect",
|
||||||
|
Ref => "Ref",
|
||||||
|
Region3 => "Region3",
|
||||||
|
Region3int16 => "Region3int16",
|
||||||
|
SharedString => "SharedString",
|
||||||
|
String => "String",
|
||||||
|
UDim => "UDim",
|
||||||
|
UDim2 => "UDim2",
|
||||||
|
Vector2 => "Vector2",
|
||||||
|
Vector2int16 => "Vector2int16",
|
||||||
|
Vector3 => "Vector3",
|
||||||
|
Vector3int16 => "Vector3int16",
|
||||||
|
OptionalCFrame => "OptionalCFrame",
|
||||||
|
_ => "?",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RbxVariantExt for RbxVariant {
|
||||||
|
fn variant_name(&self) -> &'static str {
|
||||||
|
self.ty().variant_name()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,331 +1,13 @@
|
||||||
use mlua::prelude::*;
|
|
||||||
|
|
||||||
pub(crate) use rbx_dom_weak::types::{Variant as RbxVariant, VariantType as RbxVariantType};
|
pub(crate) use rbx_dom_weak::types::{Variant as RbxVariant, VariantType as RbxVariantType};
|
||||||
|
|
||||||
// NOTE: We create a new inner module scope here to make imports of datatypes more ergonomic
|
mod conversion;
|
||||||
|
mod extension;
|
||||||
|
mod result;
|
||||||
|
mod shared;
|
||||||
|
|
||||||
mod vector2;
|
pub mod types;
|
||||||
mod vector2int16;
|
|
||||||
mod vector3;
|
|
||||||
mod vector3int16;
|
|
||||||
|
|
||||||
pub mod types {
|
use conversion::*;
|
||||||
pub use super::vector2::Vector2;
|
use extension::*;
|
||||||
pub use super::vector2int16::Vector2int16;
|
use result::*;
|
||||||
pub use super::vector3::Vector3;
|
use shared::*;
|
||||||
pub use super::vector3int16::Vector3int16;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trait definitions for conversion between rbx_dom_weak variant <-> our custom datatypes
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub(crate) enum RbxConversionError {
|
|
||||||
FromRbxVariant {
|
|
||||||
from: &'static str,
|
|
||||||
to: &'static str,
|
|
||||||
detail: Option<String>,
|
|
||||||
},
|
|
||||||
ToRbxVariant {
|
|
||||||
to: &'static str,
|
|
||||||
from: &'static str,
|
|
||||||
detail: Option<String>,
|
|
||||||
},
|
|
||||||
DesiredTypeMismatch {
|
|
||||||
can_convert_to: Option<&'static str>,
|
|
||||||
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) trait ToRbxVariant {
|
|
||||||
fn to_rbx_variant(
|
|
||||||
&self,
|
|
||||||
desired_type: Option<RbxVariantType>,
|
|
||||||
) -> RbxConversionResult<RbxVariant>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) trait FromRbxVariant: Sized {
|
|
||||||
fn from_rbx_variant(variant: &RbxVariant) -> RbxConversionResult<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) trait DatatypeTable {
|
|
||||||
fn make_dt_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shared impls for datatype metamethods belonging to this module
|
|
||||||
|
|
||||||
fn datatype_impl_to_string<D>(_: &Lua, datatype: &D, _: ()) -> LuaResult<String>
|
|
||||||
where
|
|
||||||
D: LuaUserData + ToString + 'static,
|
|
||||||
{
|
|
||||||
Ok(datatype.to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn datatype_impl_eq<D>(_: &Lua, datatype: &D, value: LuaValue) -> LuaResult<bool>
|
|
||||||
where
|
|
||||||
D: LuaUserData + PartialEq + 'static,
|
|
||||||
{
|
|
||||||
if let LuaValue::UserData(ud) = value {
|
|
||||||
if let Ok(vec) = ud.borrow::<D>() {
|
|
||||||
Ok(*datatype == *vec)
|
|
||||||
} else {
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: This implementation is .. not great, but it's the best we can
|
|
||||||
// do since we can't implement a trait like Display on a foreign type,
|
|
||||||
// and we are really only using it to make better error messages anyway
|
|
||||||
|
|
||||||
trait RbxVariantDisplayName {
|
|
||||||
fn display_name(&self) -> &'static str;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RbxVariantDisplayName for RbxVariantType {
|
|
||||||
fn display_name(&self) -> &'static str {
|
|
||||||
use RbxVariantType::*;
|
|
||||||
match self {
|
|
||||||
Axes => "Axes",
|
|
||||||
BinaryString => "BinaryString",
|
|
||||||
Bool => "Bool",
|
|
||||||
BrickColor => "BrickColor",
|
|
||||||
CFrame => "CFrame",
|
|
||||||
Color3 => "Color3",
|
|
||||||
Color3uint8 => "Color3uint8",
|
|
||||||
ColorSequence => "ColorSequence",
|
|
||||||
Content => "Content",
|
|
||||||
Enum => "Enum",
|
|
||||||
Faces => "Faces",
|
|
||||||
Float32 => "Float32",
|
|
||||||
Float64 => "Float64",
|
|
||||||
Int32 => "Int32",
|
|
||||||
Int64 => "Int64",
|
|
||||||
NumberRange => "NumberRange",
|
|
||||||
NumberSequence => "NumberSequence",
|
|
||||||
PhysicalProperties => "PhysicalProperties",
|
|
||||||
Ray => "Ray",
|
|
||||||
Rect => "Rect",
|
|
||||||
Ref => "Ref",
|
|
||||||
Region3 => "Region3",
|
|
||||||
Region3int16 => "Region3int16",
|
|
||||||
SharedString => "SharedString",
|
|
||||||
String => "String",
|
|
||||||
UDim => "UDim",
|
|
||||||
UDim2 => "UDim2",
|
|
||||||
Vector2 => "Vector2",
|
|
||||||
Vector2int16 => "Vector2int16",
|
|
||||||
Vector3 => "Vector3",
|
|
||||||
Vector3int16 => "Vector3int16",
|
|
||||||
OptionalCFrame => "OptionalCFrame",
|
|
||||||
_ => "?",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RbxVariantDisplayName for RbxVariant {
|
|
||||||
fn display_name(&self) -> &'static str {
|
|
||||||
self.ty().display_name()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 RbxVariantToLua<'lua>: Sized {
|
|
||||||
fn rbx_variant_to_lua(variant: &RbxVariant, lua: &'lua Lua) -> RbxConversionResult<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'lua> RbxVariantToLua<'lua> for LuaValue<'lua> {
|
|
||||||
fn rbx_variant_to_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::Number(*i as f64)),
|
|
||||||
Rbx::Int32(i) => Ok(LuaValue::Number(*i as f64)),
|
|
||||||
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::Vector2int16(_) => Vector2int16::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),
|
|
||||||
Rbx::Vector3int16(_) => Vector3int16::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!(),
|
|
||||||
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(v2i) = u.borrow::<Vector2int16>() {
|
|
||||||
v2i.to_rbx_variant(Some(d))
|
|
||||||
} else if let Ok(v3) = u.borrow::<Vector3>() {
|
|
||||||
v3.to_rbx_variant(Some(d))
|
|
||||||
} else if let Ok(v3i) = u.borrow::<Vector3int16>() {
|
|
||||||
v3i.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(v2i) = u.borrow::<Vector2int16>() {
|
|
||||||
v2i.to_rbx_variant(None)
|
|
||||||
} else if let Ok(v3) = u.borrow::<Vector3>() {
|
|
||||||
v3.to_rbx_variant(None)
|
|
||||||
} else if let Ok(v3i) = u.borrow::<Vector3int16>() {
|
|
||||||
v3i.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
|
|
||||||
// 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, ..
|
|
||||||
|
|
71
packages/lib-roblox/src/datatypes/result.rs
Normal file
71
packages/lib-roblox/src/datatypes/result.rs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
|
use std::io::Error as IoError;
|
||||||
|
|
||||||
|
use mlua::Error as LuaError;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub(crate) enum DatatypeConversionError {
|
||||||
|
LuaError(LuaError),
|
||||||
|
External {
|
||||||
|
message: String,
|
||||||
|
},
|
||||||
|
FromRbxVariant {
|
||||||
|
from: &'static str,
|
||||||
|
to: &'static str,
|
||||||
|
detail: Option<String>,
|
||||||
|
},
|
||||||
|
ToRbxVariant {
|
||||||
|
to: &'static str,
|
||||||
|
from: &'static str,
|
||||||
|
detail: Option<String>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for DatatypeConversionError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match self {
|
||||||
|
Self::LuaError(error) => error.to_string(),
|
||||||
|
Self::External { message } => message.to_string(),
|
||||||
|
Self::FromRbxVariant { from, to, detail }
|
||||||
|
| Self::ToRbxVariant { from, to, detail } => {
|
||||||
|
match detail {
|
||||||
|
Some(d) => format!("Failed to convert from '{from}' into '{to}' - {d}"),
|
||||||
|
None => format!("Failed to convert from '{from}' into '{to}'",),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for DatatypeConversionError {}
|
||||||
|
|
||||||
|
impl From<LuaError> for DatatypeConversionError {
|
||||||
|
fn from(value: LuaError) -> Self {
|
||||||
|
Self::LuaError(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IoError> for DatatypeConversionError {
|
||||||
|
fn from(value: IoError) -> Self {
|
||||||
|
DatatypeConversionError::External {
|
||||||
|
message: value.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<base64::DecodeError> for DatatypeConversionError {
|
||||||
|
fn from(value: base64::DecodeError) -> Self {
|
||||||
|
DatatypeConversionError::External {
|
||||||
|
message: value.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) type DatatypeConversionResult<T> = Result<T, DatatypeConversionError>;
|
23
packages/lib-roblox/src/datatypes/shared.rs
Normal file
23
packages/lib-roblox/src/datatypes/shared.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
pub(super) fn userdata_impl_to_string<D>(_: &Lua, datatype: &D, _: ()) -> LuaResult<String>
|
||||||
|
where
|
||||||
|
D: LuaUserData + ToString + 'static,
|
||||||
|
{
|
||||||
|
Ok(datatype.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn userdata_impl_eq<D>(_: &Lua, datatype: &D, value: LuaValue) -> LuaResult<bool>
|
||||||
|
where
|
||||||
|
D: LuaUserData + PartialEq + 'static,
|
||||||
|
{
|
||||||
|
if let LuaValue::UserData(ud) = value {
|
||||||
|
if let Ok(value_as_datatype) = ud.borrow::<D>() {
|
||||||
|
Ok(*datatype == *value_as_datatype)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
9
packages/lib-roblox/src/datatypes/types/mod.rs
Normal file
9
packages/lib-roblox/src/datatypes/types/mod.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
mod vector2;
|
||||||
|
mod vector2int16;
|
||||||
|
mod vector3;
|
||||||
|
mod vector3int16;
|
||||||
|
|
||||||
|
pub use vector2::Vector2;
|
||||||
|
pub use vector2int16::Vector2int16;
|
||||||
|
pub use vector3::Vector3;
|
||||||
|
pub use vector3int16::Vector3int16;
|
|
@ -4,7 +4,7 @@ use glam::{Vec2, Vec3};
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
use rbx_dom_weak::types::Vector2 as RbxVector2;
|
use rbx_dom_weak::types::Vector2 as RbxVector2;
|
||||||
|
|
||||||
use super::*;
|
use super::super::*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
An implementation of the [Vector2](https://create.roblox.com/docs/reference/engine/datatypes/Vector2)
|
An implementation of the [Vector2](https://create.roblox.com/docs/reference/engine/datatypes/Vector2)
|
||||||
|
@ -16,6 +16,26 @@ use super::*;
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct Vector2(pub Vec2);
|
pub struct Vector2(pub Vec2);
|
||||||
|
|
||||||
|
impl Vector2 {
|
||||||
|
pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
||||||
|
// Constants
|
||||||
|
datatype_table.set("xAxis", Vector2(Vec2::X))?;
|
||||||
|
datatype_table.set("yAxis", Vector2(Vec2::Y))?;
|
||||||
|
datatype_table.set("zero", Vector2(Vec2::ZERO))?;
|
||||||
|
datatype_table.set("one", Vector2(Vec2::ONE))?;
|
||||||
|
// Constructors
|
||||||
|
datatype_table.set(
|
||||||
|
"new",
|
||||||
|
lua.create_function(|_, (x, y): (Option<f32>, Option<f32>)| {
|
||||||
|
Ok(Vector2(Vec2 {
|
||||||
|
x: x.unwrap_or_default(),
|
||||||
|
y: y.unwrap_or_default(),
|
||||||
|
}))
|
||||||
|
})?,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Vector2 {
|
impl fmt::Display for Vector2 {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}, {}", self.0.x, self.0.y)
|
write!(f, "{}, {}", self.0.x, self.0.y)
|
||||||
|
@ -48,8 +68,8 @@ impl LuaUserData for Vector2 {
|
||||||
Ok(Vector2(this.0.min(rhs.0)))
|
Ok(Vector2(this.0.min(rhs.0)))
|
||||||
});
|
});
|
||||||
// Metamethods
|
// Metamethods
|
||||||
methods.add_meta_method(LuaMetaMethod::Eq, datatype_impl_eq);
|
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
|
||||||
methods.add_meta_method(LuaMetaMethod::ToString, datatype_impl_to_string);
|
methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string);
|
||||||
methods.add_meta_method(LuaMetaMethod::Unm, |_, this, ()| Ok(Vector2(-this.0)));
|
methods.add_meta_method(LuaMetaMethod::Unm, |_, this, ()| Ok(Vector2(-this.0)));
|
||||||
methods.add_meta_method(LuaMetaMethod::Add, |_, this, rhs: Vector2| {
|
methods.add_meta_method(LuaMetaMethod::Add, |_, this, rhs: Vector2| {
|
||||||
Ok(Vector2(this.0 + rhs.0))
|
Ok(Vector2(this.0 + rhs.0))
|
||||||
|
@ -100,26 +120,6 @@ impl LuaUserData for Vector2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DatatypeTable for Vector2 {
|
|
||||||
fn make_dt_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
|
||||||
// Constants
|
|
||||||
datatype_table.set("xAxis", Vector2(Vec2::X))?;
|
|
||||||
datatype_table.set("yAxis", Vector2(Vec2::Y))?;
|
|
||||||
datatype_table.set("zero", Vector2(Vec2::ZERO))?;
|
|
||||||
datatype_table.set("one", Vector2(Vec2::ONE))?;
|
|
||||||
// Constructors
|
|
||||||
datatype_table.set(
|
|
||||||
"new",
|
|
||||||
lua.create_function(|_, (x, y): (Option<f32>, Option<f32>)| {
|
|
||||||
Ok(Vector2(Vec2 {
|
|
||||||
x: x.unwrap_or_default(),
|
|
||||||
y: y.unwrap_or_default(),
|
|
||||||
}))
|
|
||||||
})?,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 })
|
||||||
|
@ -133,12 +133,12 @@ impl From<&Vector2> for RbxVector2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRbxVariant for Vector2 {
|
impl FromRbxVariant for Vector2 {
|
||||||
fn from_rbx_variant(variant: &RbxVariant) -> RbxConversionResult<Self> {
|
fn from_rbx_variant(variant: &RbxVariant) -> DatatypeConversionResult<Self> {
|
||||||
if let RbxVariant::Vector2(v) = variant {
|
if let RbxVariant::Vector2(v) = variant {
|
||||||
Ok(v.into())
|
Ok(v.into())
|
||||||
} else {
|
} else {
|
||||||
Err(RbxConversionError::FromRbxVariant {
|
Err(DatatypeConversionError::FromRbxVariant {
|
||||||
from: variant.display_name(),
|
from: variant.variant_name(),
|
||||||
to: "Vector2",
|
to: "Vector2",
|
||||||
detail: None,
|
detail: None,
|
||||||
})
|
})
|
||||||
|
@ -150,12 +150,13 @@ impl ToRbxVariant for Vector2 {
|
||||||
fn to_rbx_variant(
|
fn to_rbx_variant(
|
||||||
&self,
|
&self,
|
||||||
desired_type: Option<RbxVariantType>,
|
desired_type: Option<RbxVariantType>,
|
||||||
) -> RbxConversionResult<RbxVariant> {
|
) -> DatatypeConversionResult<RbxVariant> {
|
||||||
if matches!(desired_type, None | Some(RbxVariantType::Vector2)) {
|
if matches!(desired_type, None | Some(RbxVariantType::Vector2)) {
|
||||||
Ok(RbxVariant::Vector2(self.into()))
|
Ok(RbxVariant::Vector2(self.into()))
|
||||||
} else {
|
} else {
|
||||||
Err(RbxConversionError::DesiredTypeMismatch {
|
Err(DatatypeConversionError::ToRbxVariant {
|
||||||
can_convert_to: Some(RbxVariantType::Vector2.display_name()),
|
to: desired_type.map(|d| d.variant_name()).unwrap_or("?"),
|
||||||
|
from: "Vector2",
|
||||||
detail: None,
|
detail: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@ use glam::IVec2;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
use rbx_dom_weak::types::Vector2int16 as RbxVector2int16;
|
use rbx_dom_weak::types::Vector2int16 as RbxVector2int16;
|
||||||
|
|
||||||
use super::*;
|
use super::super::*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
An implementation of the [Vector2int16](https://create.roblox.com/docs/reference/engine/datatypes/Vector2int16)
|
An implementation of the [Vector2int16](https://create.roblox.com/docs/reference/engine/datatypes/Vector2int16)
|
||||||
|
@ -16,6 +16,20 @@ use super::*;
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct Vector2int16(pub IVec2);
|
pub struct Vector2int16(pub IVec2);
|
||||||
|
|
||||||
|
impl Vector2int16 {
|
||||||
|
pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
||||||
|
datatype_table.set(
|
||||||
|
"new",
|
||||||
|
lua.create_function(|_, (x, y): (Option<i16>, Option<i16>)| {
|
||||||
|
Ok(Vector2int16(IVec2 {
|
||||||
|
x: x.unwrap_or_default() as i32,
|
||||||
|
y: y.unwrap_or_default() as i32,
|
||||||
|
}))
|
||||||
|
})?,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Vector2int16 {
|
impl fmt::Display for Vector2int16 {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}, {}", self.0.x, self.0.y)
|
write!(f, "{}, {}", self.0.x, self.0.y)
|
||||||
|
@ -29,8 +43,8 @@ impl LuaUserData for Vector2int16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
methods.add_meta_method(LuaMetaMethod::Eq, datatype_impl_eq);
|
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
|
||||||
methods.add_meta_method(LuaMetaMethod::ToString, datatype_impl_to_string);
|
methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string);
|
||||||
methods.add_meta_method(LuaMetaMethod::Unm, |_, this, ()| Ok(Vector2int16(-this.0)));
|
methods.add_meta_method(LuaMetaMethod::Unm, |_, this, ()| Ok(Vector2int16(-this.0)));
|
||||||
methods.add_meta_method(LuaMetaMethod::Add, |_, this, rhs: Vector2int16| {
|
methods.add_meta_method(LuaMetaMethod::Add, |_, this, rhs: Vector2int16| {
|
||||||
Ok(Vector2int16(this.0 + rhs.0))
|
Ok(Vector2int16(this.0 + rhs.0))
|
||||||
|
@ -81,20 +95,6 @@ impl LuaUserData for Vector2int16 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DatatypeTable for Vector2int16 {
|
|
||||||
fn make_dt_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
|
||||||
datatype_table.set(
|
|
||||||
"new",
|
|
||||||
lua.create_function(|_, (x, y): (Option<i16>, Option<i16>)| {
|
|
||||||
Ok(Vector2int16(IVec2 {
|
|
||||||
x: x.unwrap_or_default() as i32,
|
|
||||||
y: y.unwrap_or_default() as i32,
|
|
||||||
}))
|
|
||||||
})?,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&RbxVector2int16> for Vector2int16 {
|
impl From<&RbxVector2int16> for Vector2int16 {
|
||||||
fn from(v: &RbxVector2int16) -> Self {
|
fn from(v: &RbxVector2int16) -> Self {
|
||||||
Vector2int16(IVec2 {
|
Vector2int16(IVec2 {
|
||||||
|
@ -114,12 +114,12 @@ impl From<&Vector2int16> for RbxVector2int16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRbxVariant for Vector2int16 {
|
impl FromRbxVariant for Vector2int16 {
|
||||||
fn from_rbx_variant(variant: &RbxVariant) -> RbxConversionResult<Self> {
|
fn from_rbx_variant(variant: &RbxVariant) -> DatatypeConversionResult<Self> {
|
||||||
if let RbxVariant::Vector2int16(v) = variant {
|
if let RbxVariant::Vector2int16(v) = variant {
|
||||||
Ok(v.into())
|
Ok(v.into())
|
||||||
} else {
|
} else {
|
||||||
Err(RbxConversionError::FromRbxVariant {
|
Err(DatatypeConversionError::FromRbxVariant {
|
||||||
from: variant.display_name(),
|
from: variant.variant_name(),
|
||||||
to: "Vector2int16",
|
to: "Vector2int16",
|
||||||
detail: None,
|
detail: None,
|
||||||
})
|
})
|
||||||
|
@ -131,12 +131,13 @@ impl ToRbxVariant for Vector2int16 {
|
||||||
fn to_rbx_variant(
|
fn to_rbx_variant(
|
||||||
&self,
|
&self,
|
||||||
desired_type: Option<RbxVariantType>,
|
desired_type: Option<RbxVariantType>,
|
||||||
) -> RbxConversionResult<RbxVariant> {
|
) -> DatatypeConversionResult<RbxVariant> {
|
||||||
if matches!(desired_type, None | Some(RbxVariantType::Vector2int16)) {
|
if matches!(desired_type, None | Some(RbxVariantType::Vector2int16)) {
|
||||||
Ok(RbxVariant::Vector2int16(self.into()))
|
Ok(RbxVariant::Vector2int16(self.into()))
|
||||||
} else {
|
} else {
|
||||||
Err(RbxConversionError::DesiredTypeMismatch {
|
Err(DatatypeConversionError::ToRbxVariant {
|
||||||
can_convert_to: Some(RbxVariantType::Vector2int16.display_name()),
|
to: desired_type.map(|d| d.variant_name()).unwrap_or("?"),
|
||||||
|
from: "Vector2",
|
||||||
detail: None,
|
detail: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@ use glam::Vec3;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
use rbx_dom_weak::types::Vector3 as RbxVector3;
|
use rbx_dom_weak::types::Vector3 as RbxVector3;
|
||||||
|
|
||||||
use super::*;
|
use super::super::*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
An implementation of the [Vector3](https://create.roblox.com/docs/reference/engine/datatypes/Vector3)
|
An implementation of the [Vector3](https://create.roblox.com/docs/reference/engine/datatypes/Vector3)
|
||||||
|
@ -19,6 +19,29 @@ use super::*;
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct Vector3(pub Vec3);
|
pub struct Vector3(pub Vec3);
|
||||||
|
|
||||||
|
impl Vector3 {
|
||||||
|
pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
||||||
|
// Constants
|
||||||
|
datatype_table.set("xAxis", Vector3(Vec3::X))?;
|
||||||
|
datatype_table.set("yAxis", Vector3(Vec3::Y))?;
|
||||||
|
datatype_table.set("zAxis", Vector3(Vec3::Z))?;
|
||||||
|
datatype_table.set("zero", Vector3(Vec3::ZERO))?;
|
||||||
|
datatype_table.set("one", Vector3(Vec3::ONE))?;
|
||||||
|
// Constructors
|
||||||
|
datatype_table.set(
|
||||||
|
"new",
|
||||||
|
lua.create_function(|_, (x, y, z): (Option<f32>, Option<f32>, Option<f32>)| {
|
||||||
|
Ok(Vector3(Vec3 {
|
||||||
|
x: x.unwrap_or_default(),
|
||||||
|
y: y.unwrap_or_default(),
|
||||||
|
z: z.unwrap_or_default(),
|
||||||
|
}))
|
||||||
|
})?,
|
||||||
|
)
|
||||||
|
// FUTURE: Implement FromNormalId and FromAxis constructors?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Vector3 {
|
impl fmt::Display for Vector3 {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}, {}, {}", self.0.x, self.0.y, self.0.z)
|
write!(f, "{}, {}, {}", self.0.x, self.0.y, self.0.z)
|
||||||
|
@ -59,8 +82,8 @@ impl LuaUserData for Vector3 {
|
||||||
Ok(Vector3(this.0.min(rhs.0)))
|
Ok(Vector3(this.0.min(rhs.0)))
|
||||||
});
|
});
|
||||||
// Metamethods
|
// Metamethods
|
||||||
methods.add_meta_method(LuaMetaMethod::Eq, datatype_impl_eq);
|
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
|
||||||
methods.add_meta_method(LuaMetaMethod::ToString, datatype_impl_to_string);
|
methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string);
|
||||||
methods.add_meta_method(LuaMetaMethod::Unm, |_, this, ()| Ok(Vector3(-this.0)));
|
methods.add_meta_method(LuaMetaMethod::Unm, |_, this, ()| Ok(Vector3(-this.0)));
|
||||||
methods.add_meta_method(LuaMetaMethod::Add, |_, this, rhs: Vector3| {
|
methods.add_meta_method(LuaMetaMethod::Add, |_, this, rhs: Vector3| {
|
||||||
Ok(Vector3(this.0 + rhs.0))
|
Ok(Vector3(this.0 + rhs.0))
|
||||||
|
@ -111,29 +134,6 @@ impl LuaUserData for Vector3 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DatatypeTable for Vector3 {
|
|
||||||
fn make_dt_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
|
||||||
// Constants
|
|
||||||
datatype_table.set("xAxis", Vector3(Vec3::X))?;
|
|
||||||
datatype_table.set("yAxis", Vector3(Vec3::Y))?;
|
|
||||||
datatype_table.set("zAxis", Vector3(Vec3::Z))?;
|
|
||||||
datatype_table.set("zero", Vector3(Vec3::ZERO))?;
|
|
||||||
datatype_table.set("one", Vector3(Vec3::ONE))?;
|
|
||||||
// Constructors
|
|
||||||
datatype_table.set(
|
|
||||||
"new",
|
|
||||||
lua.create_function(|_, (x, y, z): (Option<f32>, Option<f32>, Option<f32>)| {
|
|
||||||
Ok(Vector3(Vec3 {
|
|
||||||
x: x.unwrap_or_default(),
|
|
||||||
y: y.unwrap_or_default(),
|
|
||||||
z: z.unwrap_or_default(),
|
|
||||||
}))
|
|
||||||
})?,
|
|
||||||
)
|
|
||||||
// FUTURE: Implement FromNormalId and FromAxis constructors?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&RbxVector3> for Vector3 {
|
impl From<&RbxVector3> for Vector3 {
|
||||||
fn from(v: &RbxVector3) -> Self {
|
fn from(v: &RbxVector3) -> Self {
|
||||||
Vector3(Vec3 {
|
Vector3(Vec3 {
|
||||||
|
@ -155,12 +155,12 @@ impl From<&Vector3> for RbxVector3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRbxVariant for Vector3 {
|
impl FromRbxVariant for Vector3 {
|
||||||
fn from_rbx_variant(variant: &RbxVariant) -> RbxConversionResult<Self> {
|
fn from_rbx_variant(variant: &RbxVariant) -> DatatypeConversionResult<Self> {
|
||||||
if let RbxVariant::Vector3(v) = variant {
|
if let RbxVariant::Vector3(v) = variant {
|
||||||
Ok(v.into())
|
Ok(v.into())
|
||||||
} else {
|
} else {
|
||||||
Err(RbxConversionError::FromRbxVariant {
|
Err(DatatypeConversionError::FromRbxVariant {
|
||||||
from: variant.display_name(),
|
from: variant.variant_name(),
|
||||||
to: "Vector3",
|
to: "Vector3",
|
||||||
detail: None,
|
detail: None,
|
||||||
})
|
})
|
||||||
|
@ -172,12 +172,13 @@ impl ToRbxVariant for Vector3 {
|
||||||
fn to_rbx_variant(
|
fn to_rbx_variant(
|
||||||
&self,
|
&self,
|
||||||
desired_type: Option<RbxVariantType>,
|
desired_type: Option<RbxVariantType>,
|
||||||
) -> RbxConversionResult<RbxVariant> {
|
) -> DatatypeConversionResult<RbxVariant> {
|
||||||
if matches!(desired_type, None | Some(RbxVariantType::Vector3)) {
|
if matches!(desired_type, None | Some(RbxVariantType::Vector3)) {
|
||||||
Ok(RbxVariant::Vector3(self.into()))
|
Ok(RbxVariant::Vector3(self.into()))
|
||||||
} else {
|
} else {
|
||||||
Err(RbxConversionError::DesiredTypeMismatch {
|
Err(DatatypeConversionError::ToRbxVariant {
|
||||||
can_convert_to: Some(RbxVariantType::Vector3.display_name()),
|
to: desired_type.map(|d| d.variant_name()).unwrap_or("?"),
|
||||||
|
from: "Vector2",
|
||||||
detail: None,
|
detail: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@ use glam::IVec3;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
use rbx_dom_weak::types::Vector3int16 as RbxVector3int16;
|
use rbx_dom_weak::types::Vector3int16 as RbxVector3int16;
|
||||||
|
|
||||||
use super::*;
|
use super::super::*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
An implementation of the [Vector3int16](https://create.roblox.com/docs/reference/engine/datatypes/Vector3int16)
|
An implementation of the [Vector3int16](https://create.roblox.com/docs/reference/engine/datatypes/Vector3int16)
|
||||||
|
@ -16,6 +16,21 @@ use super::*;
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct Vector3int16(pub IVec3);
|
pub struct Vector3int16(pub IVec3);
|
||||||
|
|
||||||
|
impl Vector3int16 {
|
||||||
|
pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
||||||
|
datatype_table.set(
|
||||||
|
"new",
|
||||||
|
lua.create_function(|_, (x, y, z): (Option<i16>, Option<i16>, Option<i16>)| {
|
||||||
|
Ok(Vector3int16(IVec3 {
|
||||||
|
x: x.unwrap_or_default() as i32,
|
||||||
|
y: y.unwrap_or_default() as i32,
|
||||||
|
z: z.unwrap_or_default() as i32,
|
||||||
|
}))
|
||||||
|
})?,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Vector3int16 {
|
impl fmt::Display for Vector3int16 {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}, {}", self.0.x, self.0.y)
|
write!(f, "{}, {}", self.0.x, self.0.y)
|
||||||
|
@ -29,8 +44,8 @@ impl LuaUserData for Vector3int16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
methods.add_meta_method(LuaMetaMethod::Eq, datatype_impl_eq);
|
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
|
||||||
methods.add_meta_method(LuaMetaMethod::ToString, datatype_impl_to_string);
|
methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string);
|
||||||
methods.add_meta_method(LuaMetaMethod::Unm, |_, this, ()| Ok(Vector3int16(-this.0)));
|
methods.add_meta_method(LuaMetaMethod::Unm, |_, this, ()| Ok(Vector3int16(-this.0)));
|
||||||
methods.add_meta_method(LuaMetaMethod::Add, |_, this, rhs: Vector3int16| {
|
methods.add_meta_method(LuaMetaMethod::Add, |_, this, rhs: Vector3int16| {
|
||||||
Ok(Vector3int16(this.0 + rhs.0))
|
Ok(Vector3int16(this.0 + rhs.0))
|
||||||
|
@ -81,21 +96,6 @@ impl LuaUserData for Vector3int16 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DatatypeTable for Vector3int16 {
|
|
||||||
fn make_dt_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
|
||||||
datatype_table.set(
|
|
||||||
"new",
|
|
||||||
lua.create_function(|_, (x, y, z): (Option<i16>, Option<i16>, Option<i16>)| {
|
|
||||||
Ok(Vector3int16(IVec3 {
|
|
||||||
x: x.unwrap_or_default() as i32,
|
|
||||||
y: y.unwrap_or_default() as i32,
|
|
||||||
z: z.unwrap_or_default() as i32,
|
|
||||||
}))
|
|
||||||
})?,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&RbxVector3int16> for Vector3int16 {
|
impl From<&RbxVector3int16> for Vector3int16 {
|
||||||
fn from(v: &RbxVector3int16) -> Self {
|
fn from(v: &RbxVector3int16) -> Self {
|
||||||
Vector3int16(IVec3 {
|
Vector3int16(IVec3 {
|
||||||
|
@ -117,12 +117,12 @@ impl From<&Vector3int16> for RbxVector3int16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRbxVariant for Vector3int16 {
|
impl FromRbxVariant for Vector3int16 {
|
||||||
fn from_rbx_variant(variant: &RbxVariant) -> RbxConversionResult<Self> {
|
fn from_rbx_variant(variant: &RbxVariant) -> DatatypeConversionResult<Self> {
|
||||||
if let RbxVariant::Vector3int16(v) = variant {
|
if let RbxVariant::Vector3int16(v) = variant {
|
||||||
Ok(v.into())
|
Ok(v.into())
|
||||||
} else {
|
} else {
|
||||||
Err(RbxConversionError::FromRbxVariant {
|
Err(DatatypeConversionError::FromRbxVariant {
|
||||||
from: variant.display_name(),
|
from: variant.variant_name(),
|
||||||
to: "Vector3int16",
|
to: "Vector3int16",
|
||||||
detail: None,
|
detail: None,
|
||||||
})
|
})
|
||||||
|
@ -134,12 +134,13 @@ impl ToRbxVariant for Vector3int16 {
|
||||||
fn to_rbx_variant(
|
fn to_rbx_variant(
|
||||||
&self,
|
&self,
|
||||||
desired_type: Option<RbxVariantType>,
|
desired_type: Option<RbxVariantType>,
|
||||||
) -> RbxConversionResult<RbxVariant> {
|
) -> DatatypeConversionResult<RbxVariant> {
|
||||||
if matches!(desired_type, None | Some(RbxVariantType::Vector3int16)) {
|
if matches!(desired_type, None | Some(RbxVariantType::Vector3int16)) {
|
||||||
Ok(RbxVariant::Vector3int16(self.into()))
|
Ok(RbxVariant::Vector3int16(self.into()))
|
||||||
} else {
|
} else {
|
||||||
Err(RbxConversionError::DesiredTypeMismatch {
|
Err(DatatypeConversionError::ToRbxVariant {
|
||||||
can_convert_to: Some(RbxVariantType::Vector3int16.display_name()),
|
to: desired_type.map(|d| d.variant_name()).unwrap_or("?"),
|
||||||
|
from: "Vector2",
|
||||||
detail: None,
|
detail: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -8,7 +8,6 @@ pub mod instance;
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use datatypes::types::*;
|
use datatypes::types::*;
|
||||||
use datatypes::DatatypeTable;
|
|
||||||
|
|
||||||
fn make_dt<F>(lua: &Lua, f: F) -> LuaResult<LuaTable>
|
fn make_dt<F>(lua: &Lua, f: F) -> LuaResult<LuaTable>
|
||||||
where
|
where
|
||||||
|
@ -23,10 +22,10 @@ where
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
fn make_all_datatypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaTable)>> {
|
fn make_all_datatypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaTable)>> {
|
||||||
Ok(vec![
|
Ok(vec![
|
||||||
("Vector2", make_dt(lua, Vector2::make_dt_table)?),
|
("Vector2", make_dt(lua, Vector2::make_table)?),
|
||||||
("Vector2int16", make_dt(lua, Vector2int16::make_dt_table)?),
|
("Vector2int16", make_dt(lua, Vector2int16::make_table)?),
|
||||||
("Vector3", make_dt(lua, Vector3::make_dt_table)?),
|
("Vector3", make_dt(lua, Vector3::make_table)?),
|
||||||
("Vector3int16", make_dt(lua, Vector3int16::make_dt_table)?),
|
("Vector3int16", make_dt(lua, Vector3int16::make_table)?),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue