validate_directory_structure/
lib.rs

1/// Call function validate_structure
2/// ```
3/// use validate_directory_structure::ValidateDirTree;
4/// const YOUR_JSON_STRUCTUEE: &str = r#"
5/// {
6///    "name": "TEST",
7///    "description": "Structure of folders, folders required and files required",
8///    "folders": [
9///      {
10///        "required": true,
11///        "names": ["forest", "trees field"],
12///        "files": [
13///          {
14///            "required": true,
15///            "names": ["mountain", "hill"]
16///          }
17///        ],
18///        "folders": [
19///          {
20///            "names": ["sub_forest", "sub forest"],
21///            "required": true,
22///            "files": [
23///              {
24///                "names": ["file_sub_forest", "sub forest"],
25///                "required": true
26///              },
27///              {
28///                "names": ["file_optinal"],
29///                "required": false
30///              }
31///            ]
32///          }
33///        ]
34///      },
35///      {
36///        "required": false,
37///        "names": ["rivers"],
38///        "files": [
39///          {
40///            "required": true,
41///            "names": ["aaaa", "bbbbb"]
42///          }
43///        ]
44///      }
45///    ]
46/// }
47/// "#;
48/// let validate_structure = ValidateDirTree {
49///     required_extensions: vec!["shp", "dbf", "shx"],
50///     valid_extensions: vec!["txt", "md", "rs"],
51/// };
52///
53/// let results = validate_structure.validate_structure("/your/folder/path", YOUR_JSON_STRUCTUEE);
54///
55/// assert_eq!(results.len(), 2);
56///
57///
58/// ```
59///
60pub mod folders;
61
62use std::collections::HashSet;
63
64use folders::extra_files_folder::validate_extra_items;
65use folders::missing_files_folders::validate_missing_items;
66pub use folders::types::{AlertFileStructure, FolderStructure};
67
68fn merge_deduplicate<'a>(vec1: Vec<&'a str>, vec2: Vec<&'a str>) -> Vec<&'a str> {
69    let mut set: HashSet<&str> = HashSet::new();
70    set.extend(vec1);
71    set.extend(vec2);
72    set.into_iter().collect()
73}
74
75pub struct ValidateDirTree<'a> {
76    pub required_extensions: Vec<&'a str>,
77    pub valid_extensions: Vec<&'a str>,
78}
79
80impl ValidateDirTree<'_> {
81    pub fn validate_structure(
82        &self,
83        project_path: &str,
84        folder_structure_json: &str,
85    ) -> Vec<AlertFileStructure> {
86        let mut missing_items: Vec<AlertFileStructure> = vec![];
87
88        let folder_structure: FolderStructure =
89            serde_json::from_str(folder_structure_json).expect("Failed to deserialize JSON");
90
91        // Validate missing items (files/folders defined in JSON but missing in the file system)
92        validate_missing_items(
93            project_path,
94            Some(&folder_structure.folders),
95            &mut missing_items,
96            &self.required_extensions,
97        );
98
99        let all_extensions = merge_deduplicate(
100            self.required_extensions.clone(),
101            self.valid_extensions.clone(),
102        );
103
104        // // Validate extra items (files/folders in the file system but not defined in JSON)
105        validate_extra_items(
106            project_path,
107            Some(&folder_structure.folders),
108            &mut missing_items,
109            &all_extensions,
110        );
111
112        missing_items
113    }
114}