write colossal code
This commit is contained in:
parent
1ea68d96ef
commit
4fd7795457
115
src/main.rs
115
src/main.rs
@ -168,6 +168,7 @@ async fn main()->AResult<()>{
|
||||
input_folder:cli.input.unwrap(),
|
||||
output_file:cli.output.unwrap(),
|
||||
template:None,
|
||||
style:None,
|
||||
}).await,
|
||||
Commands::Decompile=>decompile(DecompileConfig{
|
||||
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)})
|
||||
}
|
||||
|
||||
async fn discern_node(search_path:&std::path::PathBuf,search_name:&str,style:Option<DecompileStyle>)->AResult<Option<CompileNode>>{
|
||||
let mut contents_folder=search_path.clone();
|
||||
contents_folder.push(search_name);
|
||||
async fn discern_node(entry:&tokio::fs::DirEntry,style:Option<DecompileStyle>)->AResult<Option<CompileNode>>{
|
||||
let contents_folder=entry.path();
|
||||
let file_name=entry.file_name();
|
||||
//folder
|
||||
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
|
||||
let script_query=async {match style{
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
async fn discern_file(entry:&tokio::fs::DirEntry,style:Option<DecompileStyle>)->AResult<Option<CompileNode>>{
|
||||
todo!();
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ScriptHint{
|
||||
Script,
|
||||
@ -1357,6 +1365,11 @@ struct FileHint{
|
||||
hint:ScriptHint,
|
||||
}
|
||||
|
||||
enum PreparedData{
|
||||
Model(rbx_dom_weak::WeakDom),
|
||||
Builder(rbx_dom_weak::InstanceBuilder),
|
||||
}
|
||||
|
||||
enum CompileClass{
|
||||
Folder,
|
||||
Script(String),
|
||||
@ -1372,8 +1385,7 @@ struct CompileNode{
|
||||
}
|
||||
|
||||
enum CompileStackInstruction{
|
||||
Referent(rbx_dom_weak::types::Ref),
|
||||
PushFolder(String),
|
||||
TraverseReferent(rbx_dom_weak::types::Ref),
|
||||
PopFolder,
|
||||
}
|
||||
|
||||
@ -1381,6 +1393,14 @@ struct CompileConfig{
|
||||
input_folder:std::path::PathBuf,
|
||||
output_file: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<()>{
|
||||
@ -1400,28 +1420,81 @@ 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<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(){
|
||||
match instruction{
|
||||
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
|
||||
todo!("this is totally unnecessary,
|
||||
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?{
|
||||
//cool
|
||||
}else{
|
||||
//determine if this is ok
|
||||
}
|
||||
//push child objects onto dom
|
||||
//push dom children objects onto stack
|
||||
CompileStackInstruction::TraverseReferent(item_ref)=>{
|
||||
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()
|
||||
};
|
||||
folder.push(sans.as_str());
|
||||
stack.push(CompileStackInstruction::PopFolder);
|
||||
stack.extend(item.children().into_iter().map(|&referent|CompileStackInstruction::Referent(referent)));
|
||||
stack.push(CompileStackInstruction::PushFolder(sanitize(item.name.as_str()).to_string()));
|
||||
//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();
|
||||
{
|
||||
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"),
|
||||
}
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user