mirror of
https://github.com/lune-org/lune.git
synced 2024-12-12 13:00:37 +00:00
Implement roblox enum datatypes
This commit is contained in:
parent
709426d8ef
commit
158603d405
6 changed files with 208 additions and 3 deletions
|
@ -173,6 +173,8 @@ impl<'lua> LuaToRbxVariant<'lua> for LuaAnyUserData<'lua> {
|
|||
RbxVariantType::Color3uint8 => convert::<Color3, rbx::Color3uint8>,
|
||||
RbxVariantType::ColorSequence => convert::<ColorSequence, rbx::ColorSequence>,
|
||||
|
||||
RbxVariantType::Enum => convert::<EnumItem, rbx::Enum>,
|
||||
|
||||
RbxVariantType::UDim => convert::<UDim, rbx::UDim>,
|
||||
RbxVariantType::UDim2 => convert::<UDim2, rbx::UDim2>,
|
||||
|
||||
|
|
64
packages/lib-roblox/src/datatypes/types/enum.rs
Normal file
64
packages/lib-roblox/src/datatypes/types/enum.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
use core::fmt;
|
||||
|
||||
use mlua::prelude::*;
|
||||
use rbx_reflection::EnumDescriptor;
|
||||
|
||||
use super::EnumItem;
|
||||
|
||||
/**
|
||||
An implementation of the [Enum](https://create.roblox.com/docs/reference/engine/datatypes/Enum) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the Enum class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Enum {
|
||||
pub(crate) desc: &'static EnumDescriptor<'static>,
|
||||
}
|
||||
|
||||
impl LuaUserData for Enum {
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_method("GetEnumItems", |_, this, ()| {
|
||||
Ok(this
|
||||
.desc
|
||||
.items
|
||||
.iter()
|
||||
.map(|(name, value)| EnumItem {
|
||||
parent: this.clone(),
|
||||
name: name.to_string(),
|
||||
value: *value,
|
||||
})
|
||||
.collect::<Vec<_>>())
|
||||
});
|
||||
methods.add_meta_method(LuaMetaMethod::Index, |_, this, name: String| {
|
||||
match this.desc.items.get(name.as_str()) {
|
||||
Some(value) => Ok(EnumItem {
|
||||
parent: this.clone(),
|
||||
name: name.to_string(),
|
||||
value: *value,
|
||||
}),
|
||||
None => Err(LuaError::RuntimeError(format!(
|
||||
"The enum item '{}' does not exist for enum '{}'",
|
||||
name, this.desc.name
|
||||
))),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Enum {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Enum.{}", self.desc.name)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Enum {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.desc.name == other.desc.name
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&'static EnumDescriptor<'static>> for Enum {
|
||||
fn from(value: &'static EnumDescriptor<'static>) -> Self {
|
||||
Self { desc: value }
|
||||
}
|
||||
}
|
86
packages/lib-roblox/src/datatypes/types/enum_item.rs
Normal file
86
packages/lib-roblox/src/datatypes/types/enum_item.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
use core::fmt;
|
||||
|
||||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::Enum as RbxEnum;
|
||||
use rbx_reflection::DataType as RbxDataType;
|
||||
|
||||
use super::Enum;
|
||||
|
||||
/**
|
||||
An implementation of the [EnumItem](https://create.roblox.com/docs/reference/engine/datatypes/EnumItem) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the EnumItem class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EnumItem {
|
||||
pub(crate) parent: Enum,
|
||||
pub(crate) name: String,
|
||||
pub(crate) value: u32,
|
||||
}
|
||||
|
||||
impl EnumItem {
|
||||
/**
|
||||
Converts an instance property into an [`EnumItem`] datatype, if the property is known.
|
||||
|
||||
Enums are not strongly typed which means we can not convert directly from a [`rbx_dom_weak::types::Enum`]
|
||||
into an `EnumItem` without losing information about its parent [`Enum`] and the `EnumItem` name.
|
||||
|
||||
This constructor exists as a shortcut to perform a [`rbx_reflection_database`] lookup for a particular
|
||||
instance class and property to construct a strongly typed `EnumItem` with no loss of information.
|
||||
*/
|
||||
#[allow(dead_code)]
|
||||
fn from_instance_property(
|
||||
class_name: impl AsRef<str>,
|
||||
prop_name: impl AsRef<str>,
|
||||
value: u32,
|
||||
) -> Option<Self> {
|
||||
let db = rbx_reflection_database::get();
|
||||
let prop = db
|
||||
.classes
|
||||
.get(class_name.as_ref())?
|
||||
.properties
|
||||
.get(prop_name.as_ref())?;
|
||||
let prop_enum = match &prop.data_type {
|
||||
RbxDataType::Enum(name) => db.enums.get(name.as_ref()),
|
||||
_ => None,
|
||||
}?;
|
||||
let enum_name = prop_enum.items.iter().find_map(|(name, v)| {
|
||||
if v == &value {
|
||||
Some(name.to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})?;
|
||||
Some(Self {
|
||||
parent: prop_enum.into(),
|
||||
name: enum_name,
|
||||
value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaUserData for EnumItem {
|
||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("Name", |_, this| Ok(this.name.clone()));
|
||||
fields.add_field_method_get("Value", |_, this| Ok(this.value));
|
||||
fields.add_field_method_get("EnumType", |_, this| Ok(this.parent.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for EnumItem {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}.{}", self.parent, self.name)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for EnumItem {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.parent == other.parent && self.value == other.value
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EnumItem> for RbxEnum {
|
||||
fn from(v: EnumItem) -> Self {
|
||||
RbxEnum::from_u32(v.value)
|
||||
}
|
||||
}
|
44
packages/lib-roblox/src/datatypes/types/enums.rs
Normal file
44
packages/lib-roblox/src/datatypes/types/enums.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
use core::fmt;
|
||||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use super::Enum;
|
||||
|
||||
/**
|
||||
An implementation of the [Enums](https://create.roblox.com/docs/reference/engine/datatypes/Enums) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the Enums class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Enums;
|
||||
|
||||
impl Enums {
|
||||
pub(crate) fn make_singleton(lua: &Lua) -> LuaResult<LuaAnyUserData> {
|
||||
lua.create_userdata(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaUserData for Enums {
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_method("GetEnums", |_, _, ()| {
|
||||
let db = rbx_reflection_database::get();
|
||||
Ok(db.enums.values().map(Enum::from).collect::<Vec<_>>())
|
||||
});
|
||||
methods.add_meta_method(LuaMetaMethod::Index, |_, _, name: String| {
|
||||
let db = rbx_reflection_database::get();
|
||||
match db.enums.get(name.as_str()) {
|
||||
Some(desc) => Ok(Enum::from(desc)),
|
||||
None => Err(LuaError::RuntimeError(format!(
|
||||
"The enum '{}' does not exist",
|
||||
name
|
||||
))),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Enums {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Enum")
|
||||
}
|
||||
}
|
|
@ -2,6 +2,9 @@ mod brick_color;
|
|||
mod color3;
|
||||
mod color_sequence;
|
||||
mod color_sequence_keypoint;
|
||||
mod r#enum;
|
||||
mod r#enum_item;
|
||||
mod r#enums;
|
||||
mod udim;
|
||||
mod udim2;
|
||||
mod vector2;
|
||||
|
@ -13,6 +16,9 @@ pub use brick_color::BrickColor;
|
|||
pub use color3::Color3;
|
||||
pub use color_sequence::ColorSequence;
|
||||
pub use color_sequence_keypoint::ColorSequenceKeypoint;
|
||||
pub use r#enum::Enum;
|
||||
pub use r#enum_item::EnumItem;
|
||||
pub use r#enums::Enums;
|
||||
pub use udim::UDim;
|
||||
pub use udim2::UDim2;
|
||||
pub use vector2::Vector2;
|
||||
|
|
|
@ -7,20 +7,21 @@ pub mod instance;
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
fn make_dt<F>(lua: &Lua, f: F) -> LuaResult<LuaTable>
|
||||
fn make_dt<F>(lua: &Lua, f: F) -> LuaResult<LuaValue>
|
||||
where
|
||||
F: Fn(&Lua, &LuaTable) -> LuaResult<()>,
|
||||
{
|
||||
let tab = lua.create_table()?;
|
||||
f(lua, &tab)?;
|
||||
tab.set_readonly(true);
|
||||
Ok(tab)
|
||||
Ok(LuaValue::Table(tab))
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn make_all_datatypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaTable)>> {
|
||||
fn make_all_datatypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaValue)>> {
|
||||
use datatypes::types::*;
|
||||
Ok(vec![
|
||||
// Classes
|
||||
("BrickColor", make_dt(lua, BrickColor::make_table)?),
|
||||
("Color3", make_dt(lua, Color3::make_table)?),
|
||||
("ColorSequence", make_dt(lua, ColorSequence::make_table)?),
|
||||
|
@ -31,6 +32,8 @@ fn make_all_datatypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaTable)>> {
|
|||
("Vector2int16", make_dt(lua, Vector2int16::make_table)?),
|
||||
("Vector3", make_dt(lua, Vector3::make_table)?),
|
||||
("Vector3int16", make_dt(lua, Vector3int16::make_table)?),
|
||||
// Singletons
|
||||
("Enum", LuaValue::UserData(Enums::make_singleton(lua)?)),
|
||||
])
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue