diff --git a/src/runner/instance.rs b/src/runner/instance.rs index a99f56e..c2b196d 100644 --- a/src/runner/instance.rs +++ b/src/runner/instance.rs @@ -6,27 +6,6 @@ use rbx_dom_weak::{InstanceBuilder,WeakDom}; use super::vector3::Vector3; -/// A store of created functions for each Roblox class. -/// Functions are created the first time they are accessed and stored in this data structure. -#[derive(Default)] -struct ClassFunctions{ - classes:HashMap<&'static str,//ClassName - HashMap<&'static str,//Function name - mlua::Function - > - > -} - -fn place_id(lua:&mlua::Lua,tuple:mlua::MultiValue)->mlua::Result{ - 0.into_lua_multi(lua) -} -type FPointer=fn(&mlua::Lua,mlua::MultiValue)->mlua::Result; -static CLASS_FUNCTION_DATABASE:phf::Map<&str,phf::Map<&str,FPointer>>=phf::phf_map!{ - "DataModel"=>phf::phf_map!{ - "GetService"=>place_id as FPointer, - } -}; - pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ //class functions store lua.set_app_data(ClassFunctions::default()); @@ -262,42 +241,9 @@ impl mlua::UserData for Instance{ _=>(), } //find a function with a matching name - if let Some(ret)=class_functions_mut(lua,|cf|{ - let class_str=instance.class.as_str(); - let f=match CLASS_FUNCTION_DATABASE.get_entry(class_str){ - Some((&static_class_str,class_functions))=>{ - match cf.classes.entry(static_class_str){ - Entry::Occupied(mut occupied_entry)=>{ - match class_functions.get_entry(index_str){ - Some((&static_index_str,function_pointer))=>{ - match occupied_entry.get_mut().entry(static_index_str){ - Entry::Occupied(occupied_entry)=>{ - Some(occupied_entry.get().clone()) - }, - Entry::Vacant(vacant_entry)=>{ - Some(vacant_entry.insert(lua.create_function(function_pointer)?).clone()) - }, - } - }, - None=>None, - } - }, - Entry::Vacant(vacant_entry)=>{ - match class_functions.get_entry(index_str){ - Some((&static_index_str,function_pointer))=>{ - let mut h=HashMap::new(); - h.entry(static_index_str).or_insert(lua.create_function(function_pointer)?); - vacant_entry.insert(h).get(static_index_str).map(|f|f.clone()) - }, - None=>None, - } - }, - } - }, - None=>None, - }; - Ok(f) - })?{ + if let Some(ret)=class_functions_mut(lua,|cf| + cf.get_or_create_class_function(lua,instance.class.as_str(),index_str) + )?{ return Ok(ret.into_lua(lua)); } //find a child with a matching name @@ -364,3 +310,67 @@ impl mlua::UserData for Instance{ }); } } + +fn place_id(lua:&mlua::Lua,tuple:mlua::MultiValue)->mlua::Result{ + 0.into_lua_multi(lua) +} +type FPointer=fn(&mlua::Lua,mlua::MultiValue)->mlua::Result; +/// A double hash map of function pointers. +/// The class tree is walked by the Instance.__index metamethod to find available class methods. +static CLASS_FUNCTION_DATABASE:phf::Map<&str,phf::Map<&str,FPointer>>=phf::phf_map!{ + "DataModel"=>phf::phf_map!{ + "GetService"=>place_id as FPointer, + } +}; + +/// A store of created functions for each Roblox class. +/// Functions are created the first time they are accessed and stored in this data structure. +#[derive(Default)] +struct ClassFunctions{ + classes:HashMap<&'static str,//ClassName + HashMap<&'static str,//Function name + mlua::Function + > + > +} +impl ClassFunctions{ + /// Someone please rewrite this, all it's supposed to do is + /// return self.classes[class][index] or create the function in the hashmap and then return it + fn get_or_create_class_function(&mut self,lua:&mlua::Lua,class:&str,index:&str)->mlua::Result>{ + // Use get_entry to get the &'static str key of the database + // and use it as a key for the classes hashmap + let f=match CLASS_FUNCTION_DATABASE.get_entry(class){ + Some((&static_class_str,class_functions))=>{ + match self.classes.entry(static_class_str){ + Entry::Occupied(mut occupied_entry)=>{ + match class_functions.get_entry(index){ + Some((&static_index_str,function_pointer))=>{ + match occupied_entry.get_mut().entry(static_index_str){ + Entry::Occupied(occupied_entry)=>{ + Some(occupied_entry.get().clone()) + }, + Entry::Vacant(vacant_entry)=>{ + Some(vacant_entry.insert(lua.create_function(function_pointer)?).clone()) + }, + } + }, + None=>None, + } + }, + Entry::Vacant(vacant_entry)=>{ + match class_functions.get_entry(index){ + Some((&static_index_str,function_pointer))=>{ + let mut h=HashMap::new(); + h.entry(static_index_str).or_insert(lua.create_function(function_pointer)?); + vacant_entry.insert(h).get(static_index_str).map(|f|f.clone()) + }, + None=>None, + } + }, + } + }, + None=>None, + }; + Ok(f) + } +}