1use std::path::Path;
3use std::path::PathBuf;
5use std::fs;
7use std::process;
9#[derive(Debug)]
10pub struct Module {
12 pub name: String,
14 pub path: PathBuf,
16 pub children: Vec<Self>,
18}
19
20impl Module<> {
21 #[allow(invalid_value)]
22 pub fn new(name: String, mist_path: PathBuf, rust_path: PathBuf) -> Self {
24 let mut this: Self = unsafe { std::mem::MaybeUninit::<Self>::zeroed().assume_init() };
25 this.constructor(name, mist_path, rust_path);
26 this
27 }
28
29 pub fn constructor(self: &mut Self, name: String, mist_path: PathBuf, rust_path: PathBuf) -> () {
31 self.children=Vec::new();
33 self.name=name;
35 self.path=mist_path;
37 if self.path.is_dir() {
39 let dir: PathBuf = self.path.clone();
41 let pkg_gate: PathBuf = self.path.join("package.mist");
43 if pkg_gate.exists() {
45 self.path=pkg_gate;
47 }
48 self.scan_directory(&dir, &rust_path);
50 }
51 } fn scan_directory(self: &mut Self, search_dir: &Path, rust_path: &Path) -> () {
53 let entries = match fs::read_dir(search_dir) { Ok (entries,) => {entries} Err (e,) => {
59 eprintln!("error: failed to read directory {}\n {}", search_dir.display(), e);
61 process::exit(1);
63 }
64 };
65 for entry in entries{
67 let entry = match entry { Ok (entry,) => {entry} Err (e,) => {
73 eprintln!("error: failed to read directory entry\n {}", e);
75 process::exit(1);
77 }
78 };
79 let child_path: PathBuf = entry.path();
81 if child_path==self.path {
83 continue
85;
86 }
87 let child_name: String = child_path.file_stem().and_then(|s| s.to_str()).expect("Failed to get module name").to_string();
89 let child_output: PathBuf = rust_path.join(&child_name).with_extension("rs");
91 if !child_path.is_dir()&&should_skip(&child_path, &child_output) {
93 continue
95;
96 }
97 self.children.push(Module::new(child_name, child_path, child_output));
99 }
100 } pub fn output_dir(self: &Self, parent_dir: &PathBuf) -> PathBuf {
102 if self.path.is_dir()||Some("package.mist")==self.path.file_name().unwrap().to_str() {
104 parent_dir.join(&self.name)
106 } else {
107 parent_dir.clone()
109 }
110 } pub fn output_path(self: &Self, parent_dir: &PathBuf) -> PathBuf {
112 if self.path.is_dir()||Some("package.mist")==self.path.file_name().unwrap().to_str() {
114 parent_dir.join(&self.name).join("mod.rs")
116 } else {
117 parent_dir.join(&self.name).with_extension("rs")
119 }
120 }}
121
122pub fn master_package(mist_path: PathBuf, rust_path: PathBuf) -> Module {
124 let name: String = mist_path.file_stem().and_then(|s| s.to_str()).expect("Failed to get module name").to_string();
126 let mut root_mod = Module::new(name, mist_path.clone(), rust_path.clone());
128 if !mist_path.is_dir() {
130 let parent_dir: PathBuf = mist_path.parent().expect("Failed to get parent directory of root file").to_path_buf();
132 root_mod.scan_directory(&parent_dir, &rust_path);
134 }
135 root_mod
137}fn should_skip(source: &Path, output: &Path) -> bool {
139 let src_time = fs::metadata(source).ok().and_then(|v| v.modified().ok());
141 let out_time = fs::metadata(output).ok().and_then(|v| v.modified().ok());
143 out_time.map(|out_time| out_time>=src_time.unwrap()).unwrap_or_default()
145}