1use std::{fs,error::Error,env};
3
4pub struct Config{
6 pub query:String,
7 pub file_path:String,
8 pub ignore_case:bool,
9}
10impl Config{
11 pub fn build(
12 mut args:impl Iterator<Item=String>,
13 )->Result<Self,&'static str>{
14
15 args.next();
16 let query=match args.next(){
17 Some(arg)=>arg,
18 None=> return Err("Query argument not provided"),
19 };
20 let file_path=match args.next(){
21 Some(arg)=>arg,
22 None=> return Err("Query argument not provided"),
23 };
24 let ignore_case=match args.next(){
25 Some(arg)=>arg=="true",
26 None=> env::var("IGNORE_CASE").is_ok(),
27 };
28
29 Ok(Self{
30 query,
31 file_path,
32 ignore_case,
33 })
34 }
35}
36
37pub fn run(config:Config)->Result<(),Box<dyn Error>>{
40 let contents=fs::read_to_string(config.file_path)?;
41 let res=if config.ignore_case{
42 search_case_insensitive(&config.query,&contents)
43 }else{
44 search(&config.query,&contents)
45 };
46
47 for x in res{
48 println!("{x}");
49 }
50 Ok(())
51}
52fn search<'a>(query:&str,content:&'a str)->Vec<&'a str>{
53 content
54 .lines()
55 .filter(|line| line.contains(&query))
56 .collect()
57}
58
59fn search_case_insensitive<'a>(query:&str,content:&'a str)->Vec<&'a str>{
60 let query=query.to_lowercase();
61 content
62 .lines()
63 .filter(|line| line.to_lowercase().contains(&query))
64 .collect()
65}
66
67#[cfg(test)]
68mod tests{
69 use super::*;
70
71 #[test]
72 fn case_sensitive(){
73 let query="Chinna";
74 let contents="\
75Chinna
76chinnachaitanya4037@gmail.com
779966547037
78B.Tech
79Gooty";
80 assert_eq!(vec!["Chinna"],search(query,contents));
81 }
82
83 #[test]
84 fn case_insensitive(){
85 let query="Chinna";
86 let contents="\
87Chinna
88chinnachaitanya4037@gmail.com
899966547037
90B.Tech
91Gooty";
92 assert_eq!(vec!["Chinna","chinnachaitanya4037@gmail.com"],search_case_insensitive(query,contents));
93 }
94}