1use std::{env, fs, process};
2use std::env::Args;
3use std::error::Error;
4
5pub struct Config {
6 query: String,
7 file_path: String,
8 pub ignore_case: bool,
9}
10
11struct SomeStruct;
12
13impl Iterator for SomeStruct {
14 type Item = i32;
15 fn next(&mut self) -> Option<Self::Item> {
16 Some(1)
17 }
18}
19
20fn some() {
21 let config = Config::build(env::args()).unwrap_or_else(|err| {
22 eprintln!("Problem parsing arguments: {err}");
23 process::exit(1);
24 });
25}
26
27
28impl Config {
29 pub fn build(
30 mut args: impl Iterator<Item=String>,
31 ) -> Result<Config, &'static str> {
32 args.next();
33
34 let query = match args.next() {
35 Some(arg) => arg,
36 None => return Err("Didn't get a query string"),
37 };
38
39 let file_path = match args.next() {
40 Some(arg) => arg,
41 None => return Err("Didn't get a file path"),
42 };
43
44 let ignore_case = env::var("IGNORE_CASE").is_ok();
45
46 Ok(Config {
47 query,
48 file_path,
49 ignore_case,
50 })
51 }
52}
53
54pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
55 let contents = fs::read_to_string(config.file_path)?;
56
57 let results = if config.ignore_case {
58 search_case_insensitive(&config.query, &contents)
59 } else {
60 search(&config.query, &contents)
61 };
62
63 for line in results {
64 println!("{line}");
65 }
66
67 Ok(())
68}
69
70
71pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
72 contents
73 .lines()
74 .filter(|line| line.contains(query))
75 .collect()
76}
77
78
79pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
80 let query = query.to_lowercase();
81 contents
82 .lines()
83 .filter(|line| line.to_lowercase().contains(&query))
84 .collect()
85}
86pub fn test_search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<String> {
87 let query = query.to_lowercase();
88 contents
89 .lines()
90 .map(|line| {
91 println!("Lowe Line {line}");
92 line.to_lowercase()
93 })
94 .filter(|line| {
95 println!("Filter Line {line}");
96 line.contains(&query)
97 })
98 .collect()
99}
100
101pub fn search_case_insensitiveold<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
102 let mut result = vec![];
103 let query = query.to_lowercase();
104 for line in contents.lines() {
105 if line.to_lowercase().contains(&query) {
106 result.push(line);
107 }
108 }
109 result
110}
111
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 const CONTENTS: &str = "\
118Rust:
119safe, fast, productive.
120Pick three.
121Duct tape.
122Trust me.";
123
124 #[test]
125 fn case_sensitive() {
126 let query = "duct";
127 assert_eq!(vec!["safe, fast, productive."], search(query, CONTENTS))
128 }
129
130 #[test]
131 fn case_insensitive() {
132 let query = "rUsT";
133 assert_eq!(
134 vec!["Rust:", "Trust me."],
135 search_case_insensitive(query, CONTENTS)
136 );
137 }
138}