use std::{fs, path::PathBuf, vec};
use anyhow::{Ok, Result};
#[derive(Debug, Clone)]
pub struct WalkFileEntry{
pub root: PathBuf,
pub child_dirs: Vec<String>,
pub child_files: Vec<String>,
}
impl WalkFileEntry {
pub fn as_tuple_ref(&self)->(&PathBuf, &Vec::<String>, &Vec::<String>){
(&self.root, &self.child_dirs, &self.child_files)
}
pub fn as_tuple(&self)->(PathBuf, Vec::<String>, Vec::<String>){
(self.root.clone(), self.child_dirs.clone(), self.child_files.clone())
}
}
impl std::fmt::Display for WalkFileEntry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "root: {}, child_dirs: {:?}, child_files:{:?}", self.root.display(), self.child_dirs, self.child_files)
}
}
pub fn walk(path: &PathBuf)->Result<Vec<WalkFileEntry>>{
let mut res:Vec<WalkFileEntry> = Vec::new();
walk_dir(path, &mut res)?;
Ok(res)
}
fn walk_dir(path: &PathBuf, res: &mut Vec<WalkFileEntry>)->Result<()>{
let mut walk = WalkFileEntry{
root: path.clone(),
child_dirs: vec![],
child_files: vec![],
};
for entry in fs::read_dir(path)?{
let entry = entry?;
if entry.path().is_dir(){
if let Some(p) = entry.path().file_name(){
if let Some(p_str) = p.to_str(){
walk.child_dirs.push(p_str.to_string());
}
}
walk_dir(&entry.path(), res)?;
}else if entry.path().is_file() {
if let Some(p) = entry.path().file_name(){
if let Some(p_file) = p.to_str(){
walk.child_files.push(p_file.to_string());
}
}
}
}
res.push(walk);
Ok(())
}
#[cfg(test)]
mod test{
use std::{path::PathBuf, str::FromStr};
use crate::walk;
#[test]
fn test_walk(){
let res = walk(&PathBuf::from_str("./").unwrap());
let res = match res {
Err(e) => panic!("{}", e),
Ok(res) => res
};
print!("{:#?}", res);
}
#[test]
fn test_ref_tuple(){
let res = walk(&PathBuf::from_str("./").unwrap());
let res = match res {
Err(e) => panic!("{}", e),
Ok(res) => res
};
let (root, child_dirs, child_files) = res[0].as_tuple();
println!("{:?}, {:?}, {:?}", root, child_dirs, child_files);
}
}