1use std::error::Error;
7use std::fs::File;
8use std::io::prelude::*;
9use std::env;
10
11pub fn run(config: Config) -> Result<(), Box<Error>> {
12 let mut file = File::open(config.filename)?;
13 let mut contents = String::new();
14 file.read_to_string(&mut contents)?;
15
16
17 let results = if config.case_sensitive {
18 search(&config.query, &contents)
19 } else {
20 search_case_insensitive(&config.query, &contents)
21 };
22
23 for line in results {
24 println!("{}", line);
25 }
26
27 Ok(())
28}
29
30pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
31 contents.lines()
32 .filter(|line| line.contains(&query))
33 .collect()
34}
35
36
37pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
51 let query = query.to_lowercase();
52
53 contents.lines()
54 .filter(|line| line.to_lowercase().contains(&query))
55 .collect()
56}
57
58pub struct Config {
59 query: String,
60 filename: String,
61 case_sensitive: bool,
62}
63
64impl Config {
65 pub fn new(mut args: std::env::Args) -> Result<Config, &'static str> {
66 if args.len() < 3 {
67 return Err("not enough arguments");
68 }
69
70 args.next(); let query = match args.next() {
73 Some(arg) => arg,
74 None => return Err("Didn't get a query string"),
75 };
76
77 let filename = match args.next() {
78 Some(arg) => arg,
79 None => return Err("Didn't get a file name"),
80 };
81
82 let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
83
84 Ok(Config { query, filename, case_sensitive })
85 }
86}
87
88
89#[cfg(test)]
90mod test {
91 use super::*;
92
93 #[test]
94 fn case_sensitive() {
95 let query = "duct";
96 let contents = "\
97Rust:
98safe, fast, productive.
99Pick three.";
100
101 assert_eq!(
102 vec!["safe, fast, productive."],
103 search(query, contents)
104 );
105 }
106
107 #[test]
108 fn case_insensitive() {
109 let query = "rUsT";
110 let contents = "\
111Rust:
112safe, fast, productive.
113Pick three.
114Trust me.";
115
116 assert_eq!(
117 vec!["Rust:", "Trust me."],
118 search_case_insensitive(query, contents)
119 );
120 }
121}