scan_lib/
lib.rs

1pub mod file_operations;
2pub mod dir_operations;
3pub mod path_manipulation;
4
5use std::collections::HashSet;
6use std::fs;
7use std::fs::File;
8use std::io::BufRead;
9use std::io::BufReader;
10use std::io::Write;
11use std::fs::OpenOptions;
12
13/// The `DirectorySearcher` struct in Rust provides functionality to search directories for specific
14/// files while maintaining a blacklist of paths.
15/// 
16/// Properties:
17/// 
18/// * `blacklist`: The `blacklist` property in the `DirectorySearcher` struct is a HashSet that stores
19/// strings representing paths that should be excluded from the search. This blacklist is used to skip
20/// certain directories during the search process.
21/// * `blacklist_file_write`: The `blacklist_file_write` property in the `DirectorySearcher` struct is
22/// of type `File`. It is used to store a file handle for writing to the blacklist file. This file
23/// handle is used to append entries to the blacklist file when needed, such as when a path is added to
24pub struct DirectorySearcher{
25    blacklist: HashSet<String>,
26    blacklist_file_write: File,
27}
28
29impl DirectorySearcher {
30    /// The function creates a new instance of DirectorySearcher with a blacklist HashSet and a file for
31    /// writing blacklist entries.
32    /// 
33    /// Returns:
34    /// 
35    /// A new instance of the `DirectorySearcher` struct is being returned.
36    pub fn new() -> Self {
37        let file= match OpenOptions::new().append(true).open("src\\blacklist.txt") {
38            Ok(file) => file,
39            Err(_e) => file_operations::new_file_return_append()
40        };
41        DirectorySearcher{
42            blacklist: HashSet::new(),
43            blacklist_file_write: file,
44        }
45    }
46    /// The function `update_blacklist` reads a file named "blacklist.txt" and updates a blacklist
47    /// collection with its contents.
48    pub fn update_blacklist(&mut self) {
49        let file: File = match OpenOptions::new().read(true).open("src\\blacklist.txt") {
50            Ok(file) => file,
51            Err(_e) => file_operations::new_file_return()
52        };
53        let reader: BufReader<File> = BufReader::new(file);
54        self.blacklist.clear();
55        for line in reader.lines() {
56            if let Ok(line) = line {
57                self.blacklist.insert(line);
58            }
59        }
60    }
61
62    /// The function searches for a specific string in file paths within a given root directory while
63    /// avoiding blacklisted paths.
64    /// 
65    /// Arguments:
66    /// 
67    /// * `root_path`: The `root_path` parameter is a reference to a string that represents the root
68    /// path from which the search operation will start. This path is the starting point for searching
69    /// for files or directories containing the specified search term.
70    /// * `be_searched_`: The `be_searched_` parameter in the `search` function is a reference to a
71    /// string that represents the keyword or phrase that is being searched for within the paths. This
72    /// parameter is expected to be in its original form without any modifications.
73    /// 
74    /// Returns:
75    /// 
76    /// A vector of strings containing the paths that match the search criteria.
77    pub(crate) fn search(&mut self, root_path: &str, be_searched_: &str) -> Vec<String> {
78        if self.blacklist.contains(&root_path.to_string()) {
79            return Vec::new();
80        }
81        let be_searched: String = be_searched_.to_lowercase();
82        let paths: Vec<String> = self.get_paths(&root_path.trim());
83        let mut matchers: Vec<String> = Vec::new();
84        let mut dirs: Vec<String> = Vec::new();
85        for i in paths.iter() {
86            if dir_operations::is_dir(i) {
87                dirs.push(i.to_string());
88            }
89            let breakers: Vec<&str> = i.split("\\").collect();
90            if breakers[breakers.len() - 1].contains(&be_searched) {
91                matchers.push(i.to_string());
92            }
93        }
94        dirs.into_iter().for_each(|dir| matchers.append(&mut self.search(&dir, &be_searched)));
95        matchers
96    }
97
98    /// The function `get_paths` reads directory contents and returns a vector of file paths, handling
99    /// errors by writing to a blacklist file if necessary.
100    /// 
101    /// Arguments:
102    /// 
103    /// * `path`: The `path` parameter in the `get_paths` function is a reference to a string (`&str`)
104    /// which represents the directory path from which you want to read the directory entries.
105    /// 
106    /// Returns:
107    /// 
108    /// The `get_paths` function returns a `Vec<String>`. If the `fs::read_dir(path)` call is
109    /// successful, it populates the vector with paths obtained from the directory entries. If there is
110    /// an error, it writes the path to a blacklist file and returns an empty vector.
111    fn get_paths(&mut self, path: &str) -> Vec<String> {
112        if let Ok(paths) = fs::read_dir(path) {
113            let mut paths_: Vec<String> = Vec::new();
114            for path in paths {
115                paths_.push(path.unwrap().path().display().to_string());
116            }
117            return paths_; 
118        } else {
119            let _ = self.blacklist_file_write.write(path.as_bytes()).unwrap();
120            let _ = self.blacklist_file_write.write(b"\n").unwrap();
121            return Vec::new();
122        }
123    }
124}
125
126#[cfg(test)]
127mod tests {
128    use super::*;
129
130    #[test]
131    pub fn is_working() {
132        let mut searcher = DirectorySearcher::new();
133        searcher.search("F:", "java");
134    }
135}