minigrep_comum_by_rust/
lib.rs1use std::fs::File;
7use std::io::prelude::*;
8use std::error::Error;
9
10pub struct Config {
11 pub query: String,
12 pub filename: String,
13 pub case_sensitive: bool,
14}
15
16impl Config {
17 pub fn new(mut args: std::env::Args) -> Result<Config, &'static str> {
18 args.next();
19
20 let query = match args.next() {
21 Some(value) => value,
22 None => return Err("query error"),
23 };
24
25 let filename = match args.next() {
26 Some(value) => value,
27 None => return Err("filename error"),
28 };
29
30 let case_sensitive = std::env::var("CASE_SENSITIVE").is_err();
31
32 Ok(Config { query, filename, case_sensitive })
33 }
34}
35
36pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
37 let mut f = File::open(config.filename)?;
38
39 let mut contents = String::new();
40 f.read_to_string(&mut contents)?;
41
42 let results = if config.case_sensitive {
43 search(&config.query, &contents)
44 }else {
45 search_case_insensitive(&config.query, &contents)
46 };
47
48 for line in results {
49 println!("{}", line);
50 }
51
52 Ok(())
53}
54
55#[cfg(test)]
56mod test {
57 use super::*;
58
59 #[test]
60 fn one_result() {
61 let query = "duct";
62 let contents = "\
63Rust:
64safe, fast, productive.
65Pick theree.
66Duct tape.";
67
68 assert_eq!(
69 vec!["safe, fast, productive."],
70 search(query, contents)
71 );
72 }
73
74 #[test]
75 fn case_insensitive() {
76 let query = "rUsT";
77 let contents = "\
78Rust:
79safe, fast, productive.
80Pick three.
81Trust me.";
82
83 assert_eq!(
84 vec!["Rust:", "Trust me."],
85 search_case_insensitive(query, contents)
86 );
87 }
88}
89
90pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
99 contents
100 .lines()
101 .filter(|line| line.contains(query))
102 .collect()
103}
104
105fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
106 contents
107 .lines()
108 .filter(|line| line.to_lowercase().contains(&query.to_lowercase()))
109 .collect()
110}