gvko_minigrep/
lib.rs

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