validate_directory_structure 0.2.5

A powerful tool to validate directory(Files and folders) structures.
Documentation
/// Call function validate_structure
/// ```
/// use validate_directory_structure::ValidateDirTree;
/// const YOUR_JSON_STRUCTUEE: &str = r#"
/// {
///    "name": "TEST",
///    "description": "Structure of folders, folders required and files required",
///    "folders": [
///      {
///        "required": true,
///        "names": ["forest", "trees field"],
///        "files": [
///          {
///            "required": true,
///            "names": ["mountain", "hill"]
///          }
///        ],
///        "folders": [
///          {
///            "names": ["sub_forest", "sub forest"],
///            "required": true,
///            "files": [
///              {
///                "names": ["file_sub_forest", "sub forest"],
///                "required": true
///              },
///              {
///                "names": ["file_optinal"],
///                "required": false
///              }
///            ]
///          }
///        ]
///      },
///      {
///        "required": false,
///        "names": ["rivers"],
///        "files": [
///          {
///            "required": true,
///            "names": ["aaaa", "bbbbb"]
///          }
///        ]
///      }
///    ]
/// }
/// "#;
/// let validate_structure = ValidateDirTree {
///     required_extensions: vec!["shp", "dbf", "shx"],
///     valid_extensions: vec!["txt", "md", "rs"],
/// };
///
/// let results = validate_structure.validate_structure("/your/folder/path", YOUR_JSON_STRUCTUEE);
/// println!("Jejejeje --- {:?}", results);
///
/// assert_eq!(results.list_of_files_found.len(), 0);
///
///
/// ```
///
pub mod folders;

use std::collections::{HashMap, HashSet};

use folders::missing_files_folders::validate_missing_items;
pub use folders::types::{AlertFileStructure, FolderStructure};
use folders::{extra_files_folder::validate_extra_items, types::ResultValidationTypes};

fn merge_deduplicate<'a>(vec1: Vec<&'a str>, vec2: Vec<&'a str>) -> Vec<&'a str> {
    let mut set: HashSet<&str> = HashSet::new();
    set.extend(vec1);
    set.extend(vec2);
    set.into_iter().collect()
}

pub struct ValidateDirTree<'a> {
    pub required_extensions: Vec<&'a str>,
    pub valid_extensions: Vec<&'a str>,
}

impl ValidateDirTree<'_> {
    pub fn validate_structure(
        &self,
        project_path: &str,
        folder_structure_json: &str,
    ) -> ResultValidationTypes {
        let mut missing_items: Vec<AlertFileStructure> = vec![];
        let mut list_of_files_found: HashMap<String, String> = HashMap::new();

        let folder_structure: FolderStructure =
            serde_json::from_str(folder_structure_json).expect("Failed to deserialize JSON");

        // Validate missing items (files/folders defined in JSON but missing in the file system)
        validate_missing_items(
            project_path,
            Some(&folder_structure.folders),
            &mut missing_items,
            &self.required_extensions,
            &mut list_of_files_found,
        );

        let all_extensions = merge_deduplicate(
            self.required_extensions.clone(),
            self.valid_extensions.clone(),
        );

        // // Validate extra items (files/folders in the file system but not defined in JSON)
        validate_extra_items(
            project_path,
            Some(&folder_structure.folders),
            &mut missing_items,
            &all_extensions,
            &mut list_of_files_found,
        );

        ResultValidationTypes {
            alert_file_structure: missing_items,
            list_of_files_found,
        }
    }
}