1
2use std::collections::HashMap;
3use std::fs::read_dir;
4use std::path::Path;
5use round::round;
6use serde::Serialize;
7
8#[derive(Debug,Serialize)]
9pub struct FileInfo {
10 pub path: String,
11 pub extension: String,
12 pub file_size_raw: u64,
13 pub file_size_label: String
14}
15
16#[derive(Debug,Serialize)]
17pub enum TreeType {
18 File(FileInfo),
19 Dir(HashMap<String,Vec<TreeType>>)
20}
21pub fn file_size_to_string(mut file_size: f64,file_size_round: i32) -> String {
29 let units: Vec<&str> = Vec::from(
30 ["b","kb","mb","gb","tb","pb"]
31 );
32 let mut selected_unit: &str = "b";
33
34 for unit in units {
35 if file_size < 1024.00 {
36 selected_unit = unit;
37 break;
38 }
39 else {
40 file_size = file_size / 1024.00;
41 }
42 }
43 format!("{}{}",round(file_size,file_size_round),selected_unit)
44}
45
46pub fn explore(base_path: &Path, data: &mut HashMap<String,Vec<TreeType>>,file_size_round: i32) {
58 match read_dir(base_path){
59 Ok(rd) => {
60 let mut inner_files: Vec<TreeType> = Vec::new();
61 for dir_entry in rd {
62 if let Ok(ref entry) = dir_entry {
63 if entry.path().is_dir() {
64 let mut inner_dirs: HashMap<String,Vec<TreeType>> = HashMap::new();
65 explore(entry.path().as_path(), &mut inner_dirs,file_size_round);
66 inner_files.push(
67 TreeType::Dir( inner_dirs)
68 );
69 }
70 else if entry.path().is_file() {
71 let file_size_raw:u64 = entry.path().metadata().unwrap().len();
72 inner_files.push(
73 TreeType::File(
74 FileInfo{
75 path: entry.file_name().to_str().unwrap().to_string(),
76 extension: entry.path().extension().unwrap().to_str().unwrap().to_string(),
77 file_size_raw,
78 file_size_label: file_size_to_string(file_size_raw as f64,file_size_round)
79 }
80 )
81 );
82 }
83 }
84 }
85 if inner_files.len() > 0 {
86 data.insert(base_path.file_name().unwrap().to_str().unwrap().to_string(), inner_files );
87 }
88 }
89 Err(error) => {
90 panic!("{}",error);
91 }
92 }
93}
94
95pub fn to_json(data: HashMap<String,Vec<TreeType>>) -> String {
108 serde_json::to_string_pretty(&data).unwrap()
109}
110
111#[cfg(test)]
112mod test_fd_mapping {
113 use super::*;
114
115 #[test]
116 fn test_explore(){
117 let base_path: String = String::from("storage/test-data");
118 let mut data: HashMap<String,Vec<TreeType>> = HashMap::new();
119 explore(Path::new(&base_path),&mut data,1);
120 let mapping:String = to_json(data);
121 println!("{}",mapping);
122 }
123 #[test]
124 fn test_file_size_converter(){
125
126 for t in vec![
127 (1024,"1kb"),
128 (1024,"1kb"),
129 (1048576,"1mb"),
130 (1073741824,"1gb"),
131 (1,"1b")
132 ] {
133 let result: String = file_size_to_string(f64::from(t.0),1);
134 println!("{:#?}",result);
135 assert_eq!(result,t.1);
136 }
137 }
138}