137 lines
4.1 KiB
Rust
137 lines
4.1 KiB
Rust
#[derive(Clone,Copy)]
|
|
pub struct EnumItem<'a>{
|
|
name:Option<&'a str>,
|
|
value:u32,
|
|
}
|
|
impl<'a> EnumItem<'a>{
|
|
fn known_name((name,&value):(&'a std::borrow::Cow<'a,str>,&u32))->Self{
|
|
Self{name:Some(name.as_ref()),value}
|
|
}
|
|
}
|
|
impl<'a> From<rbx_types::Enum> for EnumItem<'a>{
|
|
fn from(e:rbx_types::Enum)->Self{
|
|
EnumItem{
|
|
name:None,
|
|
value:e.to_u32(),
|
|
}
|
|
}
|
|
}
|
|
impl From<EnumItem<'_>> for rbx_types::Enum{
|
|
fn from(e:EnumItem)->rbx_types::Enum{
|
|
rbx_types::Enum::from_u32(e.value)
|
|
}
|
|
}
|
|
impl PartialEq for EnumItem<'_>{
|
|
fn eq(&self,other:&EnumItem<'_>)->bool{
|
|
self.value==other.value&&{
|
|
// if both names are known, they must match, otherwise whatever
|
|
match (self.name,other.name){
|
|
(Some(lhs),Some(rhs))=>lhs==rhs,
|
|
_=>true,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone,Copy)]
|
|
pub struct Enums;
|
|
impl Enums{
|
|
pub fn get(&self,index:&str)->Option<EnumItems<'static>>{
|
|
let db=rbx_reflection_database::get();
|
|
db.enums.get(index).map(|ed|EnumItems{ed})
|
|
}
|
|
}
|
|
#[derive(Clone,Copy)]
|
|
pub struct EnumItems<'a>{
|
|
ed:&'a rbx_reflection::EnumDescriptor<'a>,
|
|
}
|
|
|
|
impl<'a> EnumItems<'a>{
|
|
pub fn from_value(&self,value:u32)->Option<EnumItem<'a>>{
|
|
self.ed.items.iter().find(|&(_,&v)|v==value).map(EnumItem::known_name)
|
|
}
|
|
pub fn from_name(&self,name:&str)->Option<EnumItem<'a>>{
|
|
self.ed.items.get_key_value(name).map(EnumItem::known_name)
|
|
}
|
|
pub fn from_enum(&self,enum_item:EnumItem)->Option<EnumItem<'a>>{
|
|
match enum_item.name{
|
|
Some(s)=>{
|
|
let got=self.from_name(s)?;
|
|
(got.value==enum_item.value).then_some(got)
|
|
},
|
|
None=>self.from_value(enum_item.value)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub enum CoerceEnum<'a>{
|
|
Integer(i32),
|
|
String(mlua::String),
|
|
Enum(EnumItem<'a>),
|
|
}
|
|
impl CoerceEnum<'_>{
|
|
pub fn coerce_to<'a>(self,enum_items:EnumItems<'a>)->mlua::Result<EnumItem<'a>>{
|
|
match self{
|
|
CoerceEnum::Integer(int)=>enum_items.from_value(int as u32),
|
|
CoerceEnum::String(s)=>enum_items.from_name(&*s.to_str()?),
|
|
CoerceEnum::Enum(enum_item)=>enum_items.from_enum(enum_item),
|
|
}.ok_or_else(||mlua::Error::runtime(format!("Bad {} EnumItem",enum_items.ed.name)))
|
|
}
|
|
}
|
|
|
|
impl mlua::FromLua for CoerceEnum<'_>{
|
|
fn from_lua(value:mlua::Value,_lua:&mlua::Lua)->Result<Self,mlua::Error>{
|
|
match value{
|
|
mlua::Value::Integer(int)=>Ok(CoerceEnum::Integer(int)),
|
|
mlua::Value::String(s)=>Ok(CoerceEnum::String(s)),
|
|
mlua::Value::UserData(ud)=>Ok(CoerceEnum::Enum(*ud.borrow()?)),
|
|
other=>Err(mlua::Error::runtime(format!("Expected {} got {:?}",stringify!(Enum),other))),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn set_globals(_lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{
|
|
globals.set("Enum",Enums)
|
|
}
|
|
|
|
impl mlua::UserData for EnumItems<'static>{
|
|
fn add_fields<F:mlua::UserDataFields<Self>>(_fields:&mut F){
|
|
}
|
|
fn add_methods<M:mlua::UserDataMethods<Self>>(methods:&mut M){
|
|
methods.add_method("FromName",|_,this:&EnumItems,name:mlua::String|Ok(this.from_name(&*name.to_str()?)));
|
|
methods.add_method("FromValue",|_,this:&EnumItems,value:u32|Ok(this.from_value(value)));
|
|
methods.add_method("GetEnumItems",|_,this:&EnumItems,()|->mlua::Result<Vec<EnumItem>>{
|
|
Ok(this.ed.items.iter().map(EnumItem::known_name).collect())
|
|
});
|
|
methods.add_meta_function(mlua::MetaMethod::Index,|_,(this,val):(EnumItems,mlua::String)|{
|
|
let index=&*val.to_str()?;
|
|
Ok(this.ed.items.get_key_value(index).map(EnumItem::known_name))
|
|
});
|
|
}
|
|
}
|
|
type_from_lua_userdata_lua_lifetime!(EnumItems);
|
|
|
|
impl mlua::UserData for Enums{
|
|
fn add_fields<F:mlua::UserDataFields<Self>>(_fields:&mut F){
|
|
}
|
|
fn add_methods<M:mlua::UserDataMethods<Self>>(methods:&mut M){
|
|
methods.add_meta_function(mlua::MetaMethod::Index,|_,(enums,val):(Self,mlua::String)|{
|
|
Ok(enums.get(&*val.to_str()?))
|
|
});
|
|
}
|
|
}
|
|
type_from_lua_userdata!(Enums);
|
|
|
|
impl mlua::UserData for EnumItem<'_>{
|
|
fn add_fields<F:mlua::UserDataFields<Self>>(fields:&mut F){
|
|
fields.add_field_method_get("Name",|_,this|Ok(this.name));
|
|
fields.add_field_method_get("Value",|_,this|Ok(this.value));
|
|
}
|
|
fn add_methods<M:mlua::UserDataMethods<Self>>(methods:&mut M){
|
|
methods.add_meta_function(mlua::MetaMethod::Eq,|_,(lhs,rhs):(EnumItem<'_>,EnumItem<'_>)|{
|
|
Ok(lhs==rhs)
|
|
});
|
|
}
|
|
}
|
|
type_from_lua_userdata_lua_lifetime!(EnumItem);
|