diff --git a/lib/roblox_emulator/src/runner/enum.rs b/lib/roblox_emulator/src/runner/enum.rs index 18491a0..610bc23 100644 --- a/lib/roblox_emulator/src/runner/enum.rs +++ b/lib/roblox_emulator/src/runner/enum.rs @@ -46,6 +46,48 @@ 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 fn coerce(&self,e:CoerceEnum)->mlua::Result<EnumItem<'a>>{ + match e{ + CoerceEnum::Integer(int)=>self.from_value(int as u32), + CoerceEnum::String(s)=>self.from_name(&*s.to_str()?), + CoerceEnum::Enum(enum_item)=>self.from_enum(enum_item), + }.ok_or_else(||mlua::Error::runtime(format!("Bad {} EnumItem",self.ed.name))) + } +} + +pub enum CoerceEnum<'a>{ + Integer(i32), + String(mlua::String), + Enum(EnumItem<'a>), +} + +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) } @@ -54,6 +96,8 @@ 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()) });