jmj_minigrep/
lib.rs

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