From 07f0b03d455d8ec296d8c98296d0fb7a06752004 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 22 Jan 2024 20:28:12 -0800 Subject: [PATCH] ok I wrote this I guess --- src/main.rs | 170 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 143 insertions(+), 27 deletions(-) diff --git a/src/main.rs b/src/main.rs index b83ae55..0f1cb81 100644 --- a/src/main.rs +++ b/src/main.rs @@ -167,7 +167,7 @@ async fn main()->AResult<()>{ input_folder:cli.input.unwrap(), output_file:cli.output.unwrap(), template:None, - }), + }).await, Commands::Decompile=>decompile(DecompileConfig{ style:decompile_style.unwrap(), input_file:cli.input.unwrap(), @@ -1084,6 +1084,141 @@ async fn download_and_decompile_history_into_git(config:DownloadAndDecompileHist Ok(()) } +//holy smokes what am I doing lmao +//This giant machine is supposed to search for files according to style rules +//e.g. ScriptName.server.lua or init.lua +//Obviously I got carried away +//I could use an enum! +//I could use a struct! +//I could use a trait! +//I could use an error! +//I could use a match! +//I could use a function! +//eventually: +#[derive(Debug)] +enum QueryResolveError{ + NotFound,//0 results + Ambiguous,//>1 results + JoinError(tokio::task::JoinError), + IO(std::io::Error), +} +impl std::fmt::Display for QueryResolveError{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"{self:?}") + } +} +impl std::error::Error for QueryResolveError{} + +async fn get_file_async(mut path:std::path::PathBuf,file_name:impl AsRef)->Result{ + path.push(file_name); + match tokio::fs::File::open(path).await{ + Ok(file)=>Ok(file), + Err(e)=>match e.kind(){ + std::io::ErrorKind::NotFound=>Err(QueryResolveError::NotFound), + _=>Err(QueryResolveError::IO(e)), + }, + } +} +type QueryResult=Result; +type QueryResultHandle=tokio::task::JoinHandle; +trait Query{ + async fn resolve(self)->Result; +} +struct QuerySingle(QueryResultHandle); +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{ + match self.0.await{ + Ok(Ok(file))=>Ok(file), + Ok(Err(e))=>Err(e), + Err(e)=>Err(QueryResolveError::JoinError(e)), + } + } +} +struct QueryTriplet{ + shared:QuerySingle, + server:QuerySingle, + client:QuerySingle, +} +impl QueryTriplet{ + fn rox_rojo(search_path:&std::path::PathBuf,search_name:&str)->Self{ + Self{ + shared:QuerySingle(tokio::spawn(get_file_async(search_path.clone(),format!("{}.lua",search_name)))), + server:QuerySingle(tokio::spawn(get_file_async(search_path.clone(),format!("{}.server.lua",search_name)))), + 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,is_subfolder:bool)->Self{ + if is_subfolder{ + QueryTriplet::rox_rojo(search_path,"init") + }else{ + QueryTriplet::rox_rojo(search_path,search_name) + } + } +} +fn mega_triple_join(query_triplet:(QueryResult,QueryResult,QueryResult))->QueryResult{ + match query_triplet{ + //unambiguously locate file + (Ok(f),Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound)) + |(Err(QueryResolveError::NotFound),Ok(f),Err(QueryResolveError::NotFound)) + |(Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound),Ok(f))=>Ok(f), + //multiple files located + (Ok(_),Ok(_),Err(QueryResolveError::NotFound)) + |(Ok(_),Err(QueryResolveError::NotFound),Ok(_)) + |(Err(QueryResolveError::NotFound),Ok(_),Ok(_)) + |(Ok(_),Ok(_),Ok(_))=>Err(QueryResolveError::Ambiguous), + //no files located + (Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound),Err(QueryResolveError::NotFound))=>Err(QueryResolveError::NotFound), + //other error + (Err(e),_,_) + |(_,Err(e),_) + |(_,_,Err(e))=>Err(e) + } +} +impl Query for QueryTriplet{ + async fn resolve(self)->Result{ + let (shared,server,client)=tokio::join!(self.shared.0,self.server.0,self.client.0); + mega_triple_join(( + shared.map_err(|e|QueryResolveError::JoinError(e))?, + server.map_err(|e|QueryResolveError::JoinError(e))?, + client.map_err(|e|QueryResolveError::JoinError(e))?, + )) + } +} + +async fn find_file(search_path:&std::path::PathBuf,search_name:&str,style:Option)->AResult{ + //figure out something clever for this + let mut what=CompileNode{ + class:CompileClass::Folder, + folder:None, + }; + let mut contents_folder=search_path.clone(); + contents_folder.push(search_name); + //folder + if let Ok(dir)=tokio::fs::read_dir(contents_folder.as_path()).await{ + what.folder=Some(dir); + }else{ + contents_folder.pop(); + } + let (script_file,model_file)=tokio::join!(async {match style{ + Some(DecompileStyle::Rox)=>QuerySingle::rox(search_path,search_name).resolve().await, + Some(DecompileStyle::RoxRojo)=>QueryTriplet::rox_rojo(search_path,search_name).resolve().await, + Some(DecompileStyle::Rojo)=>QueryTriplet::rojo(search_path,search_name,what.folder.is_some()).resolve().await, + //try all three and complain if there is ambiguity + None=>mega_triple_join(tokio::join!( + QuerySingle::rox(search_path,search_name).resolve(), + QueryTriplet::rox_rojo(search_path,search_name).resolve(), + QueryTriplet::rojo(search_path,search_name,what.folder.is_some()).resolve(), + )) + }},get_file_async(search_path.clone(),format!("{}.rbxmx",search_name))); + + Ok(CompileClass::Folder) +} + enum CompileClass{ Folder, Script(String), @@ -1109,7 +1244,7 @@ struct CompileConfig{ template:Option, } -fn compile(config:CompileConfig)->AResult<()>{ +async fn compile(config:CompileConfig)->AResult<()>{ //basically decompile in reverse order //load template dom let input={ @@ -1118,6 +1253,7 @@ fn compile(config:CompileConfig)->AResult<()>{ template_path.push("template.rbxlx"); template_path }); + //mr dom doesn't like tokio files std::io::BufReader::new(std::fs::File::open(template_path)?) }; let mut dom=load_dom(input)?; @@ -1131,31 +1267,11 @@ fn compile(config:CompileConfig)->AResult<()>{ CompileStackInstruction::Referent(item_ref)=>{ let item=dom.get_by_ref(item_ref).ok_or(anyhow::Error::msg("null child ref"))?; //check if item exists in folder or subfolder of same name - let what=||async{ - //figure out something clever for this - - let mut what=CompileNode{ - class:CompileClass::Folder, - folder:None, - }; - let mut contents_folder=folder.clone(); - contents_folder.push(item.name.as_str()); - //folder - if let Ok(dir)=tokio::fs::read_dir(contents_folder.as_path()).await{ - what.folder=Some(dir); - }else{ - contents_folder.pop(); - } - //tokio::join!(a,b,c); - //rox - let mut rox_path=contents_folder.clone(); - rox_path.push(format!("{}.lua",item.name.as_str())); - if let Ok(file)=tokio::fs::File::open(rox_path).await{ - //CompileClass::ModuleScript - } - //rox-rojo - //rojo - }; + if let Ok(obj)=find_file(&folder,item.name.as_str(),None).await{ + //cool + }else{ + //determine if this is ok + } //push child objects onto dom //push dom children objects onto stack stack.push(CompileStackInstruction::PopFolder);