mirror of
https://github.com/CompeyDev/lune-packaging.git
synced 2025-01-09 12:19:09 +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};
|
||||
|
||||
// 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;
|
||||
mod vector2int16;
|
||||
mod vector3;
|
||||
mod vector3int16;
|
||||
pub mod types;
|
||||
|
||||
pub mod types {
|
||||
pub use super::vector2::Vector2;
|
||||
pub use super::vector2int16::Vector2int16;
|
||||
pub use super::vector3::Vector3;
|
||||
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, ..
|
||||
use conversion::*;
|
||||
use extension::*;
|
||||
use result::*;
|
||||
use shared::*;
|
||||
|
|
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 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)
|
||||
|
@ -16,6 +16,26 @@ use super::*;
|
|||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}, {}", self.0.x, self.0.y)
|
||||
|
@ -48,8 +68,8 @@ impl LuaUserData for Vector2 {
|
|||
Ok(Vector2(this.0.min(rhs.0)))
|
||||
});
|
||||
// Metamethods
|
||||
methods.add_meta_method(LuaMetaMethod::Eq, datatype_impl_eq);
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, datatype_impl_to_string);
|
||||
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
|
||||
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::Add, |_, this, rhs: Vector2| {
|
||||
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 {
|
||||
fn from(v: &RbxVector2) -> Self {
|
||||
Vector2(Vec2 { x: v.x, y: v.y })
|
||||
|
@ -133,12 +133,12 @@ impl From<&Vector2> for RbxVector2 {
|
|||
}
|
||||
|
||||
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 {
|
||||
Ok(v.into())
|
||||
} else {
|
||||
Err(RbxConversionError::FromRbxVariant {
|
||||
from: variant.display_name(),
|
||||
Err(DatatypeConversionError::FromRbxVariant {
|
||||
from: variant.variant_name(),
|
||||
to: "Vector2",
|
||||
detail: None,
|
||||
})
|
||||
|
@ -150,12 +150,13 @@ impl ToRbxVariant for Vector2 {
|
|||
fn to_rbx_variant(
|
||||
&self,
|
||||
desired_type: Option<RbxVariantType>,
|
||||
) -> RbxConversionResult<RbxVariant> {
|
||||
) -> DatatypeConversionResult<RbxVariant> {
|
||||
if matches!(desired_type, None | Some(RbxVariantType::Vector2)) {
|
||||
Ok(RbxVariant::Vector2(self.into()))
|
||||
} else {
|
||||
Err(RbxConversionError::DesiredTypeMismatch {
|
||||
can_convert_to: Some(RbxVariantType::Vector2.display_name()),
|
||||
Err(DatatypeConversionError::ToRbxVariant {
|
||||
to: desired_type.map(|d| d.variant_name()).unwrap_or("?"),
|
||||
from: "Vector2",
|
||||
detail: None,
|
||||
})
|
||||
}
|
|
@ -4,7 +4,7 @@ use glam::IVec2;
|
|||
use mlua::prelude::*;
|
||||
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)
|
||||
|
@ -16,6 +16,20 @@ use super::*;
|
|||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
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) {
|
||||
methods.add_meta_method(LuaMetaMethod::Eq, datatype_impl_eq);
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, datatype_impl_to_string);
|
||||
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
|
||||
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::Add, |_, this, rhs: Vector2int16| {
|
||||
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 {
|
||||
fn from(v: &RbxVector2int16) -> Self {
|
||||
Vector2int16(IVec2 {
|
||||
|
@ -114,12 +114,12 @@ impl From<&Vector2int16> for RbxVector2int16 {
|
|||
}
|
||||
|
||||
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 {
|
||||
Ok(v.into())
|
||||
} else {
|
||||
Err(RbxConversionError::FromRbxVariant {
|
||||
from: variant.display_name(),
|
||||
Err(DatatypeConversionError::FromRbxVariant {
|
||||
from: variant.variant_name(),
|
||||
to: "Vector2int16",
|
||||
detail: None,
|
||||
})
|
||||
|
@ -131,12 +131,13 @@ impl ToRbxVariant for Vector2int16 {
|
|||
fn to_rbx_variant(
|
||||
&self,
|
||||
desired_type: Option<RbxVariantType>,
|
||||
) -> RbxConversionResult<RbxVariant> {
|
||||
) -> DatatypeConversionResult<RbxVariant> {
|
||||
if matches!(desired_type, None | Some(RbxVariantType::Vector2int16)) {
|
||||
Ok(RbxVariant::Vector2int16(self.into()))
|
||||
} else {
|
||||
Err(RbxConversionError::DesiredTypeMismatch {
|
||||
can_convert_to: Some(RbxVariantType::Vector2int16.display_name()),
|
||||
Err(DatatypeConversionError::ToRbxVariant {
|
||||
to: desired_type.map(|d| d.variant_name()).unwrap_or("?"),
|
||||
from: "Vector2",
|
||||
detail: None,
|
||||
})
|
||||
}
|
|
@ -4,7 +4,7 @@ use glam::Vec3;
|
|||
use mlua::prelude::*;
|
||||
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)
|
||||
|
@ -19,6 +19,29 @@ use super::*;
|
|||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
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)))
|
||||
});
|
||||
// Metamethods
|
||||
methods.add_meta_method(LuaMetaMethod::Eq, datatype_impl_eq);
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, datatype_impl_to_string);
|
||||
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
|
||||
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::Add, |_, this, rhs: Vector3| {
|
||||
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 {
|
||||
fn from(v: &RbxVector3) -> Self {
|
||||
Vector3(Vec3 {
|
||||
|
@ -155,12 +155,12 @@ impl From<&Vector3> for RbxVector3 {
|
|||
}
|
||||
|
||||
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 {
|
||||
Ok(v.into())
|
||||
} else {
|
||||
Err(RbxConversionError::FromRbxVariant {
|
||||
from: variant.display_name(),
|
||||
Err(DatatypeConversionError::FromRbxVariant {
|
||||
from: variant.variant_name(),
|
||||
to: "Vector3",
|
||||
detail: None,
|
||||
})
|
||||
|
@ -172,12 +172,13 @@ impl ToRbxVariant for Vector3 {
|
|||
fn to_rbx_variant(
|
||||
&self,
|
||||
desired_type: Option<RbxVariantType>,
|
||||
) -> RbxConversionResult<RbxVariant> {
|
||||
) -> DatatypeConversionResult<RbxVariant> {
|
||||
if matches!(desired_type, None | Some(RbxVariantType::Vector3)) {
|
||||
Ok(RbxVariant::Vector3(self.into()))
|
||||
} else {
|
||||
Err(RbxConversionError::DesiredTypeMismatch {
|
||||
can_convert_to: Some(RbxVariantType::Vector3.display_name()),
|
||||
Err(DatatypeConversionError::ToRbxVariant {
|
||||
to: desired_type.map(|d| d.variant_name()).unwrap_or("?"),
|
||||
from: "Vector2",
|
||||
detail: None,
|
||||
})
|
||||
}
|
|
@ -4,7 +4,7 @@ use glam::IVec3;
|
|||
use mlua::prelude::*;
|
||||
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)
|
||||
|
@ -16,6 +16,21 @@ use super::*;
|
|||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
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) {
|
||||
methods.add_meta_method(LuaMetaMethod::Eq, datatype_impl_eq);
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, datatype_impl_to_string);
|
||||
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
|
||||
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::Add, |_, this, rhs: Vector3int16| {
|
||||
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 {
|
||||
fn from(v: &RbxVector3int16) -> Self {
|
||||
Vector3int16(IVec3 {
|
||||
|
@ -117,12 +117,12 @@ impl From<&Vector3int16> for RbxVector3int16 {
|
|||
}
|
||||
|
||||
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 {
|
||||
Ok(v.into())
|
||||
} else {
|
||||
Err(RbxConversionError::FromRbxVariant {
|
||||
from: variant.display_name(),
|
||||
Err(DatatypeConversionError::FromRbxVariant {
|
||||
from: variant.variant_name(),
|
||||
to: "Vector3int16",
|
||||
detail: None,
|
||||
})
|
||||
|
@ -134,12 +134,13 @@ impl ToRbxVariant for Vector3int16 {
|
|||
fn to_rbx_variant(
|
||||
&self,
|
||||
desired_type: Option<RbxVariantType>,
|
||||
) -> RbxConversionResult<RbxVariant> {
|
||||
) -> DatatypeConversionResult<RbxVariant> {
|
||||
if matches!(desired_type, None | Some(RbxVariantType::Vector3int16)) {
|
||||
Ok(RbxVariant::Vector3int16(self.into()))
|
||||
} else {
|
||||
Err(RbxConversionError::DesiredTypeMismatch {
|
||||
can_convert_to: Some(RbxVariantType::Vector3int16.display_name()),
|
||||
Err(DatatypeConversionError::ToRbxVariant {
|
||||
to: desired_type.map(|d| d.variant_name()).unwrap_or("?"),
|
||||
from: "Vector2",
|
||||
detail: None,
|
||||
})
|
||||
}
|
|
@ -8,7 +8,6 @@ pub mod instance;
|
|||
mod tests;
|
||||
|
||||
use datatypes::types::*;
|
||||
use datatypes::DatatypeTable;
|
||||
|
||||
fn make_dt<F>(lua: &Lua, f: F) -> LuaResult<LuaTable>
|
||||
where
|
||||
|
@ -23,10 +22,10 @@ where
|
|||
#[rustfmt::skip]
|
||||
fn make_all_datatypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaTable)>> {
|
||||
Ok(vec![
|
||||
("Vector2", make_dt(lua, Vector2::make_dt_table)?),
|
||||
("Vector2int16", make_dt(lua, Vector2int16::make_dt_table)?),
|
||||
("Vector3", make_dt(lua, Vector3::make_dt_table)?),
|
||||
("Vector3int16", make_dt(lua, Vector3int16::make_dt_table)?),
|
||||
("Vector2", make_dt(lua, Vector2::make_table)?),
|
||||
("Vector2int16", make_dt(lua, Vector2int16::make_table)?),
|
||||
("Vector3", make_dt(lua, Vector3::make_table)?),
|
||||
("Vector3int16", make_dt(lua, Vector3int16::make_table)?),
|
||||
])
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue