From 5384bbcb3bfc6f7900b8ae63617557632f1a4888 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 23 Jan 2024 18:43:23 -0800 Subject: [PATCH] support Script.module.lua properly --- src/main.rs | 156 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 117 insertions(+), 39 deletions(-) diff --git a/src/main.rs b/src/main.rs index 47b6c15..f876ed6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1120,32 +1120,31 @@ async fn get_file_async(mut path:std::path::PathBuf,file_name:impl AsRef; -type QueryResultHandle=tokio::task::JoinHandle; +type QueryHintResult=Result; trait Query{ - async fn resolve(self)->Result; + async fn resolve(self)->QueryHintResult; } -struct QuerySingle(QueryResultHandle); +struct QuerySingle(tokio::task::JoinHandle>); impl QuerySingle{ fn rox(search_path:&std::path::PathBuf,search_name:&str)->Self{ Self(tokio::spawn(get_file_async(search_path.clone(),format!("{}.lua",search_name)))) } } impl Query for QuerySingle{ - async fn resolve(self)->Result{ + async fn resolve(self)->QueryHintResult{ match self.0.await{ - Ok(Ok(file))=>Ok(file), + Ok(Ok(file))=>Ok(FileHint{file,hint:ScriptHint::Undetermined}), Ok(Err(e))=>Err(e), Err(e)=>Err(QueryResolveError::JoinError(e)), } } } -struct QueryTriplet{ +struct QueryTriple{ module:QuerySingle, server:QuerySingle, client:QuerySingle, } -impl QueryTriplet{ +impl QueryTriple{ fn rox_rojo(search_path:&std::path::PathBuf,search_name:&str,search_module:bool)->Self{ //this should be implemented as constructors of Triplet and Quadruplet to fully support Trey's suggestion let module_name=if search_module{ @@ -1159,15 +1158,28 @@ impl QueryTriplet{ client:QuerySingle(tokio::spawn(get_file_async(search_path.clone(),format!("{}.client.lua",search_name)))), } } - fn rojo(search_path:&std::path::PathBuf,search_name:&str,search_module:bool,is_subfolder:bool)->Self{ - if is_subfolder{ - QueryTriplet::rox_rojo(search_path,"init",search_module) - }else{ - QueryTriplet::rox_rojo(search_path,search_name,search_module) - } + fn rojo(search_path:&std::path::PathBuf,search_name:&str)->Self{ + QueryTriple::rox_rojo(search_path,"init",false) } } -fn mega_triple_join(query_triplet:(QueryResult,QueryResult,QueryResult))->QueryResult{ +//these functions can be achieved with macros, but I have not learned that yet +fn mega_double_join(query_pair:(QueryHintResult,QueryHintResult))->QueryHintResult{ + match query_pair{ + //unambiguously locate file + (Ok(f),Err(QueryResolveError::NotFound)) + |(Err(QueryResolveError::NotFound),Ok(f))=>Ok(f), + //multiple files located + (Ok(_),Err(QueryResolveError::NotFound)) + |(Err(QueryResolveError::NotFound),Ok(_)) + |(Ok(_),Ok(_))=>Err(QueryResolveError::Ambiguous), + //no files located + (Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound))=>Err(QueryResolveError::NotFound), + //other error + (Err(e),_) + |(_,Err(e))=>Err(e), + } +} +fn mega_triple_join(query_triplet:(QueryHintResult,QueryHintResult,QueryHintResult))->QueryHintResult{ match query_triplet{ //unambiguously locate file (Ok(f),Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound)) @@ -1183,16 +1195,73 @@ fn mega_triple_join(query_triplet:(QueryResult,QueryResult,QueryResult))->QueryR //other error (Err(e),_,_) |(_,Err(e),_) - |(_,_,Err(e))=>Err(e) + |(_,_,Err(e))=>Err(e), } } -impl Query for QueryTriplet{ - async fn resolve(self)->Result{ +//LETS GOOOOOOOOOOOOOOOO +fn mega_quadruple_join(query_quad:(QueryHintResult,QueryHintResult,QueryHintResult,QueryHintResult))->QueryHintResult{ + match query_quad{ + //unambiguously locate file + (Ok(f),Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound)) + |(Err(QueryResolveError::NotFound),Ok(f),Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound)) + |(Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound),Ok(f),Err(QueryResolveError::NotFound)) + |(Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound),Ok(f))=>Ok(f), + //multiple files located + (Ok(_),Ok(_),Ok(_),Err(QueryResolveError::NotFound)) + |(Ok(_),Ok(_),Err(QueryResolveError::NotFound),Ok(_)) + |(Ok(_),Ok(_),Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound)) + |(Ok(_),Err(QueryResolveError::NotFound),Ok(_),Ok(_)) + |(Ok(_),Err(QueryResolveError::NotFound),Ok(_),Err(QueryResolveError::NotFound)) + |(Ok(_),Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound),Ok(_)) + |(Err(QueryResolveError::NotFound),Ok(_),Ok(_),Ok(_)) + |(Err(QueryResolveError::NotFound),Ok(_),Ok(_),Err(QueryResolveError::NotFound)) + |(Err(QueryResolveError::NotFound),Ok(_),Err(QueryResolveError::NotFound),Ok(_)) + |(Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound),Ok(_),Ok(_)) + |(Ok(_),Ok(_),Ok(_),Ok(_))=>Err(QueryResolveError::Ambiguous), + //no files located + (Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound))=>Err(QueryResolveError::NotFound), + //other error + (Err(e),_,_,_) + |(_,Err(e),_,_) + |(_,_,Err(e),_) + |(_,_,_,Err(e))=>Err(e), + } +} +impl Query for QueryTriple{ + async fn resolve(self)->QueryHintResult{ let (module,server,client)=tokio::join!(self.module.0,self.server.0,self.client.0); mega_triple_join(( - module.map_err(|e|QueryResolveError::JoinError(e))?, - server.map_err(|e|QueryResolveError::JoinError(e))?, - client.map_err(|e|QueryResolveError::JoinError(e))?, + module.map_err(|e|QueryResolveError::JoinError(e))?.map(|file|FileHint{file,hint:ScriptHint::ModuleScript}), + server.map_err(|e|QueryResolveError::JoinError(e))?.map(|file|FileHint{file,hint:ScriptHint::Script}), + client.map_err(|e|QueryResolveError::JoinError(e))?.map(|file|FileHint{file,hint:ScriptHint::LocalScript}), + )) + } +} +struct QueryQuad{ + module_implicit:QuerySingle, + module_explicit:QuerySingle, + server:QuerySingle, + client:QuerySingle, +} +impl QueryQuad{ + fn rox_rojo(search_path:&std::path::PathBuf,search_name:&str)->Self{ + let fill=QueryTriple::rox_rojo(search_path,search_name,true); + Self{ + module_implicit:QuerySingle::rox(search_path,search_name),//Script.lua + module_explicit:fill.module,//Script.module.lua + server:fill.server, + client:fill.client, + } + } +} +impl Query for QueryQuad{ + async fn resolve(self)->QueryHintResult{ + let (module_implicit,module_explicit,server,client)=tokio::join!(self.module_implicit.0,self.module_explicit.0,self.server.0,self.client.0); + mega_quadruple_join(( + module_implicit.map_err(|e|QueryResolveError::JoinError(e))?.map(|file|FileHint{file,hint:ScriptHint::ModuleScript}), + module_explicit.map_err(|e|QueryResolveError::JoinError(e))?.map(|file|FileHint{file,hint:ScriptHint::ModuleScript}), + server.map_err(|e|QueryResolveError::JoinError(e))?.map(|file|FileHint{file,hint:ScriptHint::Script}), + client.map_err(|e|QueryResolveError::JoinError(e))?.map(|file|FileHint{file,hint:ScriptHint::LocalScript}), )) } } @@ -1203,25 +1272,23 @@ async fn discern_node(search_path:&std::path::PathBuf,search_name:&str,style:Opt //folder Ok(if let Ok(dir)=tokio::fs::read_dir(contents_folder.as_path()).await{ //scan inside the folder for an object to define the class of the folder - let (script_file,model_file)=tokio::join!( - async {match style{ - Some(DecompileStyle::Rox)=>QuerySingle::rox(&contents_folder,search_name).resolve().await, - Some(DecompileStyle::RoxRojo)=>QueryTriplet::rox_rojo(&contents_folder,search_name,false).resolve().await, - Some(DecompileStyle::Rojo)=>QueryTriplet::rojo(&contents_folder,search_name,false,true).resolve().await, - //try all three and complain if there is ambiguity - None=>mega_triple_join(tokio::join!( - QuerySingle::rox(&contents_folder,search_name).resolve(), - //true=search for module here to avoid ambiguity with QuerySingle::rox results - QueryTriplet::rox_rojo(&contents_folder,search_name,true).resolve(), - QueryTriplet::rojo(&contents_folder,search_name,true,true).resolve(), - )) - }}, - //model files are rox & rox-rojo only, so it's a lot less work... - get_file_async(contents_folder.clone(),format!("{}.rbxmx",search_name)) - ); + let script_query=async {match style{ + Some(DecompileStyle::Rox)=>QuerySingle::rox(&contents_folder,search_name).resolve().await, + Some(DecompileStyle::RoxRojo)=>QueryQuad::rox_rojo(&contents_folder,search_name).resolve().await, + Some(DecompileStyle::Rojo)=>QueryTriple::rojo(&contents_folder,search_name).resolve().await, + //try all three and complain if there is ambiguity + None=>mega_triple_join(tokio::join!( + QuerySingle::rox(&contents_folder,search_name).resolve(), + //true=search for module here to avoid ambiguity with QuerySingle::rox results + QueryTriple::rox_rojo(&contents_folder,search_name,true).resolve(), + QueryTriple::rojo(&contents_folder,search_name).resolve(), + )) + }}; + //model files are rox & rox-rojo only, so it's a lot less work... + let model_query=get_file_async(contents_folder.clone(),format!("{}.rbxmx",search_name)); //model? script? both? - Some(match (script_file,model_file){ - (Ok(mut file),Err(QueryResolveError::NotFound))=>{ + Some(match tokio::join!(script_query,model_query){ + (Ok(FileHint{mut file,hint}),Err(QueryResolveError::NotFound))=>{ //read entire file let mut buf=String::new(); file.read_to_string(&mut buf).await?; @@ -1259,6 +1326,17 @@ async fn discern_node(search_path:&std::path::PathBuf,search_name:&str,style:Opt }) } +enum ScriptHint{ + Script, + LocalScript, + ModuleScript, + Undetermined, +} +struct FileHint{ + file:tokio::fs::File, + hint:ScriptHint, +} + enum CompileClass{ Folder, Script(String),