minigrep_extremq/
lib.rs

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