grep_rust/
lib.rs

1use std::error::Error;
2use std::fs::File;
3use std::io::Read;
4use std::{env, io};
5
6pub struct Config {
7    query: String,
8    filename: String,
9    case_sensitive: bool,
10}
11
12impl Config {
13    pub fn new(mut args: env::Args) -> Result<Config, &'static str> {
14        args.next();
15        let query = match args.next() {
16            Some(arg) => arg,
17            None => return Err("query is nil"),
18        };
19        let filename = match args.next() {
20            Some(arg) => arg,
21            None => return Err("filename is nil"),
22        };
23        let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
24        Ok(Config {
25            query,
26            filename,
27            case_sensitive,
28        })
29    }
30}
31
32pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
33    let contents = read_file(&config.filename)?;
34    let result = if config.case_sensitive {
35        search(&config.query, &contents)
36    } else {
37        search_case_sensitive(&config.query, &contents)
38    };
39    for line in result.iter() {
40        println!("{}", line);
41    }
42    Ok(())
43}
44
45fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
46    contents
47        .lines()
48        .filter(|line| line.contains(query))
49        .map(|line| line.trim())
50        .collect()
51}
52
53fn search_case_sensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
54    contents
55        .lines()
56        .filter(|line| line.to_lowercase().contains(&query.to_lowercase()))
57        .map(|line| line.trim())
58        .collect()
59}
60
61fn read_file(path: &str) -> Result<String, io::Error> {
62    let mut s = String::new();
63    File::open(path)?.read_to_string(&mut s)?;
64    Ok(s)
65}
66
67#[cfg(test)]
68mod test {
69    use super::*;
70
71    #[test]
72    fn one_result() {
73        let query = "Apache";
74        let filename = "./LICENSE";
75        let contents = read_file(filename).unwrap();
76        let results = search(query, contents.as_str());
77        for line in results.iter() {
78            println!("matching line : {}", line);
79        }
80        assert!(results.len() > 0)
81    }
82}