endixk_minigrep/
lib.rs

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