1use crate::CaseMode::CaseSensitive;
2use CaseMode::CaseInsensitive;
3use std::error::Error;
4use std::{env, fs};
5
6pub fn run(config: &Config) -> Result<(), Box<dyn Error>> {
7 let content = fs::read_to_string(&config.file_path)?;
8
9 search(&config.query, &content, &config.case_mode)
10 .iter()
11 .for_each(|matching_string| println!("Found {matching_string}"));
12
13 Ok(())
14}
15
16fn search<'a>(query: &str, content: &'a str, case_mode: &CaseMode) -> Vec<&'a str> {
17 content
18 .lines()
19 .filter(|l| match case_mode {
20 CaseSensitive => l.contains(query),
21 CaseInsensitive => l.to_lowercase().contains(&query.to_lowercase()),
22 })
23 .collect::<Vec<_>>()
24}
25
26enum CaseMode {
27 CaseInsensitive,
28 CaseSensitive,
29}
30
31pub struct Config {
32 pub query: String,
33 pub file_path: String,
34 pub(crate) case_mode: CaseMode,
35}
36impl Config {
37 pub fn build(mut arguments: impl Iterator<Item = String>) -> Result<Self, &'static str> {
38 arguments.next();
39
40 let query = arguments.next().ok_or("query string not supplied")?;
41 let file_path = arguments.next().ok_or("file path not supplied")?;
42 let case_mode = Self::case_mode()?;
43
44 Ok(Config {
45 query,
46 file_path,
47 case_mode,
48 })
49 }
50
51 fn case_mode() -> Result<CaseMode, &'static str> {
52 let case_mode = match env::var("CASE_MODE").as_deref().unwrap_or("sensitive") {
53 "sensitive" => CaseSensitive,
54 "insensitive" => CaseInsensitive,
55 _ => return Err("Invalid case mode"),
56 };
57 Ok(case_mode)
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn finds_a_case_sensitive_matching_result() {
67 let query = "duct";
68 let content = "\
69Rust:
70safe, fast, productive.
71Pick three.
72Duct tape.";
73
74 let results = search(query, content, &CaseSensitive);
75
76 assert_eq!(vec!["safe, fast, productive."], results)
77 }
78
79 #[test]
80 fn finds_case_sensitive_matching_result() {
81 let query = "RuSt";
82 let content = "\
83Rust:
84safe, fast, productive.
85Pick three.
86Duct tape.";
87 let results = search(query, content, &CaseInsensitive);
88
89 assert_eq!(vec!["Rust:"], results);
90 }
91}