diff --git a/src/main.rs b/src/main.rs index 2a228e4..66f490e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1111,10 +1111,16 @@ impl std::fmt::Display for QueryResolveError{ } impl std::error::Error for QueryResolveError{} -async fn get_file_async(mut path:std::path::PathBuf,file_name:impl AsRef)->Result{ +struct FileWithName{ + file:tokio::fs::File, + name:String, +} + +async fn get_file_async(mut path:std::path::PathBuf,file_name:impl AsRef)->Result{ + let name=file_name.as_ref().to_str().unwrap().to_owned(); path.push(file_name); match tokio::fs::File::open(path).await{ - Ok(file)=>Ok(file), + Ok(file)=>Ok(FileWithName{file,name}), Err(e)=>match e.kind(){ std::io::ErrorKind::NotFound=>Err(QueryResolveError::NotFound), _=>Err(QueryResolveError::IO(e)), @@ -1125,7 +1131,7 @@ type QueryHintResult=Result; trait Query{ async fn resolve(self)->QueryHintResult; } -type QueryHandle=tokio::task::JoinHandle>; +type QueryHandle=tokio::task::JoinHandle>; struct QuerySingle{ script:QueryHandle, } @@ -1281,14 +1287,15 @@ fn extract_script_overrides(mut source:String)->AResult{ Ok(ScriptWithOverrides{overrides,source:source.split_off(count)}) } -async fn script_node(search_name:&str,mut file:tokio::fs::File,hint:ScriptHint)->AResult{ +async fn script_node(search_name:&str,mut file:FileWithName,hint:ScriptHint)->AResult{ //read entire file let mut buf=String::new(); - file.read_to_string(&mut buf).await?; + file.file.read_to_string(&mut buf).await?; //regex script according to Properties lines at the top let script_with_overrides=extract_script_overrides(buf)?; //script Ok(CompileNode{ + blacklist:Some(file.name), name:script_with_overrides.overrides.name.unwrap_or_else(||search_name.to_owned()), class:match (script_with_overrides.overrides.class.as_deref(),hint){ (Some("ModuleScript"),_) @@ -1302,13 +1309,14 @@ async fn script_node(search_name:&str,mut file:tokio::fs::File,hint:ScriptHint)- }) } -async fn model_node(search_name:&str,mut file:tokio::fs::File)->AResult{ +async fn model_node(search_name:&str,mut file:FileWithName)->AResult{ //read entire file let mut buf=Vec::new(); - file.read_to_end(&mut buf).await?; + file.file.read_to_end(&mut buf).await?; //model Ok(CompileNode{ - name:search_name.to_owned(), + blacklist:Some(file.name), + name:search_name.to_owned(),//wrong but gets overwritten by internal model name class:CompileClass::Model(buf), }) } @@ -1340,6 +1348,7 @@ async fn locate_override_file(entry:&tokio::fs::DirEntry,style:OptionCompileNode{ name:search_name.to_owned(), + blacklist:None, class:CompileClass::Folder, }, //other error @@ -1399,8 +1408,8 @@ async fn discern_file(entry:&tokio::fs::DirEntry,style:Option)-> file_name.truncate(file_name.len()-ext_len); let file=tokio::fs::File::open(entry.path()).await?; Ok(match file_discernment{ - FileDiscernment::Model=>model_node(file_name.as_str(),file).await?, - FileDiscernment::Script(hint)=>script_node(file_name.as_str(),file,hint).await?, + FileDiscernment::Model=>model_node(file_name.as_str(),FileWithName{file,name:file_name.clone()}).await?, + FileDiscernment::Script(hint)=>script_node(file_name.as_str(),FileWithName{file,name:file_name.clone()},hint).await?, }) } @@ -1411,7 +1420,7 @@ enum ScriptHint{ ModuleScript, } struct FileHint{ - file:tokio::fs::File, + file:FileWithName, hint:ScriptHint, } @@ -1430,11 +1439,12 @@ enum CompileClass{ struct CompileNode{ name:String, + blacklist:Option, class:CompileClass, } enum CompileStackInstruction{ - TraverseReferent(rbx_dom_weak::types::Ref), + TraverseReferent(rbx_dom_weak::types::Ref,Option), PopFolder, } @@ -1469,10 +1479,10 @@ async fn compile(config:CompileConfig)->AResult<()>{ //add in scripts and models let mut folder=config.input_folder.clone(); folder.push("src"); - let mut stack:Vec=dom.root().children().into_iter().map(|&referent|CompileStackInstruction::TraverseReferent(referent)).collect(); + let mut stack:Vec=dom.root().children().into_iter().map(|&referent|CompileStackInstruction::TraverseReferent(referent,None)).collect(); while let Some(instruction)=stack.pop(){ match instruction{ - CompileStackInstruction::TraverseReferent(item_ref)=>{ + CompileStackInstruction::TraverseReferent(item_ref,blacklist)=>{ let sans={ let item=dom.get_by_ref(item_ref).ok_or(anyhow::Error::msg("null child ref"))?; sanitize(item.name.as_str()).to_string() @@ -1482,6 +1492,9 @@ async fn compile(config:CompileConfig)->AResult<()>{ //check if a folder exists with item.name if let Ok(mut dir)=tokio::fs::read_dir(folder.as_path()).await{ let mut exist_names=std::collections::HashSet::new(); + if let Some(dont)=blacklist{ + exist_names.insert(dont); + } { let item=dom.get_by_ref(item_ref).ok_or(anyhow::Error::msg("null child ref"))?; for &child_ref in item.children(){ @@ -1508,28 +1521,37 @@ async fn compile(config:CompileConfig)->AResult<()>{ //discern that bad boy Ok::<_,anyhow::Error>( //prepare data structure - match compile_class.class{ + (compile_class.blacklist,match compile_class.class{ CompileClass::Folder=>PreparedData::Builder(rbx_dom_weak::InstanceBuilder::new("Folder").with_name(compile_class.name.as_str())), CompileClass::Script(source)=>PreparedData::Builder(script_builder("Script",compile_class.name.as_str(),source)), CompileClass::LocalScript(source)=>PreparedData::Builder(script_builder("LocalScript",compile_class.name.as_str(),source)), CompileClass::ModuleScript(source)=>PreparedData::Builder(script_builder("ModuleScript",compile_class.name.as_str(),source)), CompileClass::Model(buf)=>PreparedData::Model(rbx_xml::from_reader_default(std::io::Cursor::new(buf))?), - } + }) ) }); } } - //this is only able to begin after dir iterator is exhausted + //push existing dom children objects onto stack + { + let item=dom.get_by_ref(item_ref).ok_or(anyhow::Error::msg("null child ref"))?; + stack.extend(item.children().into_iter().map(|&referent|CompileStackInstruction::TraverseReferent(referent,None))) + }; //push child objects onto dom + //this is only able to begin after dir iterator is exhausted while let Some(goober)=join_set.join_next().await{ - match goober??{ - PreparedData::Model(mut model_dom)=>model_dom.transfer(model_dom.root().children()[0],&mut dom,item_ref), - PreparedData::Builder(script)=>{dom.insert(item_ref,script);}, - } + let (blacklist,data)=goober??; + let referent=match data{ + PreparedData::Model(mut model_dom)=>{ + let referent=model_dom.root().children()[0]; + model_dom.transfer(referent,&mut dom,item_ref); + referent + }, + PreparedData::Builder(script)=>dom.insert(item_ref,script), + }; + //new children need to be traversed + stack.push(CompileStackInstruction::TraverseReferent(referent,blacklist)); } - //push dom children objects onto stack - let item=dom.get_by_ref(item_ref).ok_or(anyhow::Error::msg("null child ref"))?; - stack.extend(item.children().into_iter().map(|&referent|CompileStackInstruction::TraverseReferent(referent))); } }, CompileStackInstruction::PopFolder=>assert!(folder.pop(),"pop folder bad"),