]>
Commit | Line | Data |
---|---|---|
1 | use std::error::Error; | |
2 | use std::fs; | |
3 | ||
4 | pub struct Config { | |
5 | pub query: String, | |
6 | pub file_path: String, | |
7 | } | |
8 | ||
9 | impl Config { | |
10 | pub fn build(args: &[String]) -> Result<Config, &'static str> { | |
11 | if args.len() < 3 { | |
12 | return Err("not enough arguments"); | |
13 | } | |
14 | ||
15 | let query = args[1].clone(); | |
16 | let file_path = args[2].clone(); | |
17 | ||
18 | Ok(Config { query, file_path }) | |
19 | } | |
20 | } | |
21 | ||
22 | // ANCHOR: here | |
23 | pub fn run(config: Config) -> Result<(), Box<dyn Error>> { | |
24 | let contents = fs::read_to_string(config.file_path)?; | |
25 | ||
26 | for line in search(&config.query, &contents) { | |
27 | println!("{line}"); | |
28 | } | |
29 | ||
30 | Ok(()) | |
31 | } | |
32 | // ANCHOR_END: here | |
33 | ||
34 | pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { | |
35 | let mut results = Vec::new(); | |
36 | ||
37 | for line in contents.lines() { | |
38 | if line.contains(query) { | |
39 | results.push(line); | |
40 | } | |
41 | } | |
42 | ||
43 | results | |
44 | } | |
45 | ||
46 | #[cfg(test)] | |
47 | mod tests { | |
48 | use super::*; | |
49 | ||
50 | #[test] | |
51 | fn one_result() { | |
52 | let query = "duct"; | |
53 | let contents = "\ | |
54 | Rust: | |
55 | safe, fast, productive. | |
56 | Pick three."; | |
57 | ||
58 | assert_eq!(vec!["safe, fast, productive."], search(query, contents)); | |
59 | } | |
60 | } |