massimans_minigrep/
lib.rs

1use std::{env, error::Error, fs};
2pub struct Config {
3    pub query: String,
4    pub file_name: String,
5    pub ignore_case: bool,
6}
7#[derive(Debug)]
8pub struct SearchResult<'a> {
9    pub line_number: usize,
10    pub line: &'a str,
11}
12impl Config {
13    pub fn new() -> Result<Config, &'static str> {
14        let args: Vec<String> = env::args().collect();
15        if args.len() < 3 {
16            return Err("minigrep expects exactly 2 arguments");
17        }
18        let ignore_case =
19            env::var("IGNORE_CASE").is_ok() || args.contains(&String::from("--ignore-case"));
20        Ok(Config {
21            query: args[1].clone(),
22            file_name: args[2].clone(),
23            ignore_case,
24        })
25    }
26}
27pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
28    let content = fs::read_to_string(&config.file_name)?;
29    let results = if config.ignore_case {
30        search_case_insensitive(&config.query, &content)
31    } else {
32        search(&config.query, &content)
33    };
34    for line in results {
35        println!("{}:{}", line.line_number, line.line);
36    }
37    Ok(())
38}
39pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<SearchResult<'a>> {
40    let query = query.to_lowercase();
41    contents
42        .lines()
43        .enumerate()
44        .map(|(index, line)| SearchResult {
45            line_number: index + 1,
46            line,
47        })
48        .filter(|result| result.line.to_lowercase().contains(&query))
49        .collect()
50}
51pub fn search<'a>(query: &str, contents: &'a str) -> Vec<SearchResult<'a>> {
52    contents
53        .lines()
54        .enumerate()
55        .map(|(index, line)| SearchResult {
56            line_number: index + 1,
57            line,
58        })
59        .filter(|result| result.line.contains(query))
60        .collect()
61}
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn one_result() {
68        let query = "duct";
69        let contents = "\
70Rust:
71safe, fast, productive.
72Pick three.";
73        let result = search(query, contents);
74        assert_eq!(result[0].line, "safe, fast, productive.");
75        assert_eq!(result[0].line_number, 2);
76    }
77}