nitesh_minigrep/
lib.rs

1use std::env;
2use std::error::Error;
3use std::fs;
4
5pub struct Config {
6    pub query: String,
7    pub file_path: String,
8    pub ignore_case: bool,
9}
10pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
11    let contents = fs::read_to_string(config.file_path)?;
12
13    let results = if config.ignore_case {
14        search_case_insensitive(&config.query, &contents)
15    } else {
16        search(&config.query, &contents)
17    };
18
19    for line in results {
20        println!("{line}");
21    }
22
23    Ok(())
24}
25
26impl Config {
27    pub fn build(mut args: impl Iterator<Item = String>) -> Result<Config, &'static str> {
28        args.next(); // the first value in the return value of env::args is the name of the program.
29
30        let query = match args.next() {
31            Some(arg) => arg,
32            None => return Err("Didn't get a query string"),
33        };
34
35        let file_path = match args.next() {
36            Some(arg) => arg,
37            None => return Err("Didn't get a file path"),
38        };
39
40        let ignore_case = env::var("IGNORE_CASE").is_ok();
41
42        Ok(Config {
43            query,
44            file_path,
45            ignore_case,
46        })
47    }
48}
49
50pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
51    contents
52        .lines()
53        .filter(|line| line.contains(query))
54        .collect()
55
56    // let mut results = Vec::new();
57    // for line in contents.lines() {
58    //     if line.contains(query) {
59    //         results.push(line);
60    //     }
61    // }
62    // results
63}
64
65pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
66    let query = query.to_lowercase();
67    contents
68        .lines()
69        .filter(|line| line.to_lowercase().contains(&query))
70        .collect()
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76
77    #[test]
78    fn one_result() {
79        let query = "duct";
80        let contents = "\
81Rust:
82safe, fast, productive.
83Pick three.";
84
85        assert_eq!(vec!["safe, fast, productive."], search(query, contents));
86    }
87
88    #[test]
89    fn case_insensitive() {
90        let query = "rUsT";
91        let contents = "\
92Rust:
93safe, fast, productive.
94Pick three.
95Trust me.";
96
97        assert_eq!(
98            vec!["Rust:", "Trust me."],
99            search_case_insensitive(query, contents)
100        );
101    }
102}