qubaitian_minigrep/
lib.rs

1//! # My Crate
2//!
3//! `my_crate` is a collection of utilities to make performing certain
4//! calculations more convenient.
5
6use std::env;
7use std::error::Error;
8use std::fs;
9
10pub struct Config {
11    pub query: String,
12    pub file_path: String,
13    pub ignore_case: bool,
14}
15
16impl Config {
17    pub fn build(mut args: impl Iterator<Item = String>) -> Result<Config, &'static str> {
18        args.next();
19
20        let query = match args.next() {
21            Some(arg) => arg,
22            None => return Err("Didn't get a query string"),
23        };
24
25        let file_path = match args.next() {
26            Some(arg) => arg,
27            None => return Err("Didn't get a file path"),
28        };
29
30        let ignore_case = env::var("IGNORE_CASE").is_ok();
31
32        Ok(Config {
33            query,
34            file_path,
35            ignore_case,
36        })
37    }
38}
39
40pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
41    let contents = fs::read_to_string(config.file_path)?;
42
43    let results = if config.ignore_case {
44        search_case_insensitive(&config.query, &contents)
45    } else {
46        search(&config.query, &contents)
47    };
48
49    for line in results {
50        println!("{line}");
51    }
52    Ok(())
53}
54
55pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
56    let mut results = Vec::new();
57
58    for line in contents.lines() {
59        if line.contains(query) {
60            results.push(line);
61        }
62    }
63
64    results
65}
66
67pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
68    let query = query.to_lowercase();
69    let mut results = Vec::new();
70
71    for line in contents.lines() {
72        if line.to_lowercase().contains(&query) {
73            results.push(line);
74        }
75    }
76    results
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    #[test]
84    fn case_sensitive() {
85        let query = "duct";
86        let contents = "\
87Rust:
88safe, fast, productive.
89Pick three.
90Duct tape.";
91
92        assert_eq!(vec!["safe, fast, productive."], search(query, contents));
93    }
94
95    #[test]
96    fn case_insensitive() {
97        let query = "rUsT";
98        let contents = "\
99Rust:
100safe, fast, productive.
101Pick three.
102Trust me.";
103
104        assert_eq!(
105            vec!["Rust:", "Trust me."],
106            search_case_insensitive(query, contents)
107        );
108    }
109}
110
111/// Adds one to the number given.
112///
113/// # Examples
114///
115/// ```
116/// let arg = 5;
117/// let answer = minigrep::add_one(arg);
118///
119/// assert_eq!(6, answer);
120/// ```
121pub fn add_one(x: i32) -> i32 {
122    x + 1
123}