minigrep5/new/
lib2.rs

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}