write colossal code

This commit is contained in:
Quaternions 2024-01-23 23:55:14 -08:00
parent 1ea68d96ef
commit 4fd7795457

View File

@ -168,6 +168,7 @@ async fn main()->AResult<()>{
input_folder:cli.input.unwrap(), input_folder:cli.input.unwrap(),
output_file:cli.output.unwrap(), output_file:cli.output.unwrap(),
template:None, template:None,
style:None,
}).await, }).await,
Commands::Decompile=>decompile(DecompileConfig{ Commands::Decompile=>decompile(DecompileConfig{
style:decompile_style.unwrap(), style:decompile_style.unwrap(),
@ -1275,11 +1276,12 @@ fn extract_script_overrides(mut source:String)->AResult<ScriptWithOverrides>{
Ok(ScriptWithOverrides{overrides,source:source.split_off(count)}) Ok(ScriptWithOverrides{overrides,source:source.split_off(count)})
} }
async fn discern_node(search_path:&std::path::PathBuf,search_name:&str,style:Option<DecompileStyle>)->AResult<Option<CompileNode>>{ async fn discern_node(entry:&tokio::fs::DirEntry,style:Option<DecompileStyle>)->AResult<Option<CompileNode>>{
let mut contents_folder=search_path.clone(); let contents_folder=entry.path();
contents_folder.push(search_name); let file_name=entry.file_name();
//folder //folder
Ok(if let Ok(dir)=tokio::fs::read_dir(contents_folder.as_path()).await{ Ok(if let Ok(dir)=tokio::fs::read_dir(contents_folder.as_path()).await{
let search_name=file_name.to_str().unwrap();
//scan inside the folder for an object to define the class of the folder //scan inside the folder for an object to define the class of the folder
let script_query=async {match style{ let script_query=async {match style{
Some(DecompileStyle::Rox)=>QuerySingle::rox(&contents_folder,search_name).resolve().await, Some(DecompileStyle::Rox)=>QuerySingle::rox(&contents_folder,search_name).resolve().await,
@ -1345,6 +1347,12 @@ async fn discern_node(search_path:&std::path::PathBuf,search_name:&str,style:Opt
None None
}) })
} }
async fn discern_file(entry:&tokio::fs::DirEntry,style:Option<DecompileStyle>)->AResult<Option<CompileNode>>{
todo!();
Ok(None)
}
#[derive(Debug)] #[derive(Debug)]
enum ScriptHint{ enum ScriptHint{
Script, Script,
@ -1357,6 +1365,11 @@ struct FileHint{
hint:ScriptHint, hint:ScriptHint,
} }
enum PreparedData{
Model(rbx_dom_weak::WeakDom),
Builder(rbx_dom_weak::InstanceBuilder),
}
enum CompileClass{ enum CompileClass{
Folder, Folder,
Script(String), Script(String),
@ -1372,8 +1385,7 @@ struct CompileNode{
} }
enum CompileStackInstruction{ enum CompileStackInstruction{
Referent(rbx_dom_weak::types::Ref), TraverseReferent(rbx_dom_weak::types::Ref),
PushFolder(String),
PopFolder, PopFolder,
} }
@ -1381,6 +1393,14 @@ struct CompileConfig{
input_folder:std::path::PathBuf, input_folder:std::path::PathBuf,
output_file:std::path::PathBuf, output_file:std::path::PathBuf,
template:Option<std::path::PathBuf>, template:Option<std::path::PathBuf>,
style:Option<DecompileStyle>,
}
fn script_builder(class:&str,name:&str,source:String)->rbx_dom_weak::InstanceBuilder{
let mut builder=rbx_dom_weak::InstanceBuilder::new(class);
builder.set_name(name);
builder.add_property("Source",rbx_dom_weak::types::Variant::String(source));
builder
} }
async fn compile(config:CompileConfig)->AResult<()>{ async fn compile(config:CompileConfig)->AResult<()>{
@ -1400,28 +1420,81 @@ async fn compile(config:CompileConfig)->AResult<()>{
//add in scripts and models //add in scripts and models
let mut folder=config.input_folder.clone(); let mut folder=config.input_folder.clone();
folder.push("src"); folder.push("src");
let mut stack:Vec<CompileStackInstruction>=dom.root().children().into_iter().map(|&referent|CompileStackInstruction::Referent(referent)).collect(); let mut stack:Vec<CompileStackInstruction>=dom.root().children().into_iter().map(|&referent|CompileStackInstruction::TraverseReferent(referent)).collect();
while let Some(instruction)=stack.pop(){ while let Some(instruction)=stack.pop(){
match instruction{ match instruction{
CompileStackInstruction::Referent(item_ref)=>{ CompileStackInstruction::TraverseReferent(item_ref)=>{
let item=dom.get_by_ref(item_ref).ok_or(anyhow::Error::msg("null child ref"))?; let sans={
//check if item exists in folder or subfolder of same name let item=dom.get_by_ref(item_ref).ok_or(anyhow::Error::msg("null child ref"))?;
todo!("this is totally unnecessary, sanitize(item.name.as_str()).to_string()
only the folder needs to exist to determine if traversal should continue"); };
if let Some(obj)=discern_node(&folder,item.name.as_str(),None).await?{ folder.push(sans.as_str());
//cool
}else{
//determine if this is ok
}
//push child objects onto dom
//push dom children objects onto stack
stack.push(CompileStackInstruction::PopFolder); stack.push(CompileStackInstruction::PopFolder);
stack.extend(item.children().into_iter().map(|&referent|CompileStackInstruction::Referent(referent))); //check if a folder exists with item.name
stack.push(CompileStackInstruction::PushFolder(sanitize(item.name.as_str()).to_string())); if let Ok(mut dir)=tokio::fs::read_dir(folder.as_path()).await{
let mut exist_names=std::collections::HashSet::new();
{
let item=dom.get_by_ref(item_ref).ok_or(anyhow::Error::msg("null child ref"))?;
for &child_ref in item.children(){
let child=dom.get_by_ref(child_ref).ok_or(anyhow::Error::msg("null child ref"))?;
let child_sans=sanitize(child.name.as_str()).to_string();
exist_names.insert(child_sans);
}
}
//generate children from folder contents UNLESS! item already has a child of the same name
let mut join_set=tokio::task::JoinSet::new();
//I wish I could make the join_next() loop begin processing immediately,
//but I don't know an ergonomic way to do that.
//this will probably be fine considering there won't be millions of files in the directories
while let Some(entry)=dir.next_entry().await?{
//cull early even if supporting things with identical names is possible
if !exist_names.contains(entry.file_name().to_str().unwrap()){
let style=config.style;
join_set.spawn(async move{
//discern that bad boy
match tokio::join!(discern_node(&entry,style),discern_file(&entry,style)){
(Ok(Some(compile_class)),Ok(None))
|(Ok(None),Ok(Some(compile_class)))=>{
//prepare data structure
match compile_class.class{
CompileClass::Folder=>Ok(Some(PreparedData::Builder(rbx_dom_weak::InstanceBuilder::new("Folder").with_name(compile_class.name.as_str())))),
CompileClass::Script(source)=>Ok(Some(PreparedData::Builder(script_builder("Script",compile_class.name.as_str(),source)))),
CompileClass::LocalScript(source)=>Ok(Some(PreparedData::Builder(script_builder("LocalScript",compile_class.name.as_str(),source)))),
CompileClass::ModuleScript(source)=>Ok(Some(PreparedData::Builder(script_builder("ModuleScript",compile_class.name.as_str(),source)))),
CompileClass::Model(buf)=>Ok(Some(PreparedData::Model(rbx_xml::from_reader_default(std::io::Cursor::new(buf))?))),
}
},
(Ok(Some(_)),Ok(Some(_)))=>panic!("File and folder have the same name!"),
(Ok(None),Ok(None))=>Ok(None),
(Err(e),_)
|(_,Err(e))=>Err(e),
}
});
}
}
//this is only able to begin after dir iterator is exhausted
//push child objects onto dom
while let Some(goober)=join_set.join_next().await{
match goober??{
Some(PreparedData::Model(mut model_dom))=>model_dom.transfer(model_dom.root().children()[0],&mut dom,item_ref),
Some(PreparedData::Builder(script))=>{dom.insert(item_ref,script);},
None=>print!("There was a None"),
}
}
//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::PushFolder(component)=>folder.push(component),
CompileStackInstruction::PopFolder=>assert!(folder.pop(),"pop folder bad"), CompileStackInstruction::PopFolder=>assert!(folder.pop(),"pop folder bad"),
} }
} }
let mut output_place=config.output_file.clone();
if output_place.extension().is_none(){
output_place.push("place.rbxl");
}
let output=std::io::BufWriter::new(std::fs::File::open(output_place)?);
rbx_binary::to_writer(output,&dom,&[dom.root_ref()])?;
Ok(()) Ok(())
} }