minigrep_nepelover/
lib.rs1use std::io::BufRead;
5pub struct Config{
6 query: String,
7 file_path: String,
8 ignore_case: bool,
9}
10
11impl Config {
12 pub fn query(&self) -> &str{
13 self.query.as_str()
14 }
15
16 pub fn file_path(&self) -> &str{
17 self.file_path.as_str()
18 }
19
20 pub fn ignore_case(&self) -> &bool{
21 &self.ignore_case
22 }
23
24 pub fn build(
25 mut args: impl Iterator<Item = String>,
26 ) -> Result<Config, &'static str>{
27 args.next();
28
29 let query = match args.next() {
30 Some(arg) => arg,
31 None => return Err("Did not get a query string"),
32 };
33
34 let file_path = match args.next() {
35 Some(arg) => arg,
36 None => return Err("Did not get a file path"),
37 };
38
39 Ok(
40 Config {
41 query: query,
42 file_path: file_path,
43 ignore_case: std::env::var("IGNORE_CASE").is_ok(),
44 }
45 )
46 }
47 pub fn run(&self) -> Result<(), Box<dyn std::error::Error>>{
48 let file = std::fs::File::open(self.file_path.as_str())?;
49
50 let reader = std::io::BufReader::new(file);
51
52 let contents:String = reader.lines().filter_map(
53 |line|{
54 if let None = line.as_ref().ok(){
55 None
56 } else {
57 Some(format!("{}\n", line.unwrap()))
58 }
59 }
60 ).collect();
61
62 let results:Vec<&str> = if self.ignore_case{
63 search_case_insensitive(self.query.as_str(), &contents)
64 } else{
65 search(self.query.as_str(), &contents)
66 };
67
68 for line in results{
69 println!("{line}");
70 }
71
72 Ok(())
73 }
74
75}
76pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str>{
90 contents.lines().filter(
91 |l|{
92 l.contains(query)
93 }
94 ).collect()
95}
96
97pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str>{
98 contents.lines().filter(
99 |line|{
100 line.to_lowercase().contains(&query.to_lowercase())
101 }
102 ).collect()
103}
104
105#[cfg(test)]
106mod tests{
107 use super::*;
108
109 #[test]
110 fn case_sensitive(){
111 let query = "duct";
112 let contents = "\
113Rust:
114safe, fast, productive.
115Pick three.
116Duck tape.";
117
118 assert_eq!(vec!["safe, fast, productive."], search(query, contents));
119 }
120
121 #[test]
122 fn case_insensitive(){
123 let query = "rUsT";
124 let contents = "\
125Rust:
126safe, fast, productive.
127Pick three.
128Trust me.";
129
130 assert_eq!(
131 vec!["Rust:", "Trust me."],
132 search_case_insensitive(query, contents)
133 );
134 }
135
136}