validate_directory_structure 0.2.5

A powerful tool to validate directory(Files and folders) structures.
Documentation
use std::{collections::HashMap, fs};

use std::path::Path;

use super::get_base_name::get_base_name;
use super::types::{AlertFileStructure, AlertType, FileTypes, Folder, ItemType};

pub fn validate_extra_items(
    path: &str,
    folders: Option<&Vec<Folder>>,
    missing_items: &mut Vec<AlertFileStructure>,
    valid_extensions: &Vec<&str>,
    list_of_files_found: &mut HashMap<String, String>,
) {
    let base_path = Path::new(path);

    if let Some(folders) = folders {
        if let Ok(entries) = fs::read_dir(base_path) {
            let mut match_folder_name = true;
            for entry in entries.flatten() {
                let path_entry = entry.path();
                let entry_folder_name = path_entry
                    .file_name()
                    .unwrap()
                    .to_string_lossy()
                    .to_string();

                for folder in folders {
                    if path_entry.is_dir() {
                        match_folder_name = folder
                            .names
                            .iter()
                            .any(|name| name.to_lowercase() == entry_folder_name.to_lowercase());

                        let mut exist_sub_folders = false;
                        // Recursively validate subfolders
                        if let Some(subfolders) = &folder.folders {
                            exist_sub_folders = true;
                            validate_extra_items(
                                format!("{}/{}", path, entry_folder_name).as_str(),
                                Some(subfolders),
                                missing_items,
                                valid_extensions,
                                list_of_files_found,
                            );
                        }

                        if match_folder_name {
                            //validate extra files
                            if let Some(files) = &folder.files {
                                validate_files(
                                    &path_entry,
                                    files,
                                    missing_items,
                                    valid_extensions.clone(),
                                    !exist_sub_folders,
                                    folder.id.as_ref().unwrap_or(&"".to_string()),
                                    list_of_files_found,
                                );
                            }
                            break;
                        }
                    }
                }
                if !match_folder_name {
                    missing_items.push(AlertFileStructure {
                        path: format!("{}/{}", path, entry_folder_name),
                        item_type: ItemType::Folder,
                        alert_type: AlertType::ExtraItem,
                    });
                    continue;
                }
            }
        }
    }
}

fn validate_files(
    folder_path: &Path,
    files: &Vec<FileTypes>,
    missing_items: &mut Vec<AlertFileStructure>,
    valid_extensions: Vec<&str>,
    check_folder: bool,
    id_folder: &String,
    list_of_files_found: &mut HashMap<String, String>,
) {
    if let Ok(entries) = fs::read_dir(folder_path) {
        for entry in entries.flatten() {
            let path_entry = entry.path();
            let file_name_entry = path_entry
                .file_name()
                .unwrap()
                .to_string_lossy()
                .to_string();
            let mut defined_files: HashMap<String, String> = HashMap::new();

            if path_entry.is_file() {
                for file in files {
                    for name in &file.names {
                        for ext in valid_extensions.iter() {
                            let full_file_name_json_with_ext = format!("{}.{}", name, ext);
                            defined_files.insert(
                                full_file_name_json_with_ext.to_lowercase(),
                                file.id.clone().unwrap_or_default(),
                            );
                        }
                    }
                }

                if !defined_files.contains_key(&file_name_entry.to_lowercase()) {
                    missing_items.push(AlertFileStructure {
                        path: format!("{}/{}", folder_path.to_string_lossy(), file_name_entry),
                        item_type: ItemType::File,
                        alert_type: AlertType::ExtraItem,
                    });
                } else {
                    list_of_files_found.insert(
                        format!(
                            "{}-{}",
                            id_folder,
                            defined_files.get(&file_name_entry.to_lowercase()).unwrap()
                        ),
                        format!(
                            "{}/{}",
                            folder_path.to_string_lossy(),
                            get_base_name(file_name_entry.as_str())
                        ),
                    );
                }
                continue;
            }
            if check_folder {
                missing_items.push(AlertFileStructure {
                    path: format!("{}", path_entry.as_path().to_string_lossy()),
                    item_type: ItemType::Folder,
                    alert_type: AlertType::ExtraItem,
                });
            }
        }
    }
}