minigrep_leo_hu/
lib.rs

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