Skip to content

Commit cb86d09

Browse files
committed
rust book minigrep
1 parent 212a951 commit cb86d09

File tree

6 files changed

+124
-0
lines changed

6 files changed

+124
-0
lines changed

rust/minigrep/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/target

rust/minigrep/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/minigrep/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "minigrep"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[dependencies]

rust/minigrep/poem.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
I'm nobody! Who are you?
2+
Are you nobody, too?
3+
Then there's a pair of us - don't tell!
4+
They'd banish us, you know.
5+
6+
How dreary to be somebody!
7+
How public, like a frog
8+
To tell your name the livelong day
9+
To an admiring bog!

rust/minigrep/src/lib.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
2+
let mut results = Vec::new();
3+
for line in contents.lines() {
4+
if line.contains(query) {
5+
results.push(line);
6+
}
7+
}
8+
results
9+
}
10+
11+
pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
12+
let query = query.to_lowercase();
13+
let mut results = Vec::new();
14+
for line in contents.lines() {
15+
if line.to_lowercase().contains(&query) {
16+
results.push(line);
17+
}
18+
}
19+
results
20+
}
21+
#[cfg(test)]
22+
mod tests {
23+
use super::*;
24+
25+
#[test]
26+
fn case_sensitive() {
27+
let query = "duct";
28+
let contents = "\
29+
Rust:
30+
safe, fast, productive.
31+
Pick three.
32+
Duct tape.";
33+
assert_eq!(vec!["safe, fast, productive."], search(query, contents))
34+
}
35+
36+
#[test]
37+
fn case_insensitive() {
38+
let query = "rUsT";
39+
let contents = "\
40+
Rust:
41+
safe, fast, productive.
42+
Pick three.
43+
Trust me.";
44+
assert_eq!(
45+
vec!["Rust:", "Trust me."],
46+
search_case_insensitive(query, contents)
47+
)
48+
}
49+
}

rust/minigrep/src/main.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use minigrep::{search, search_case_insensitive};
2+
use std::env;
3+
use std::error::Error;
4+
use std::fs;
5+
use std::process;
6+
7+
fn main() {
8+
let args: Vec<String> = env::args().collect();
9+
let config = Config::build(&args).unwrap_or_else(|e| {
10+
eprintln!("Problem parsing args: {e}");
11+
process::exit(1);
12+
});
13+
if let Err(e) = run(config) {
14+
eprintln!("Application error: {e}");
15+
process::exit(1);
16+
}
17+
}
18+
19+
fn run(config: Config) -> Result<(), Box<dyn Error>> {
20+
let contents = fs::read_to_string(config.file_path)?;
21+
let results = if config.ignore_case {
22+
search_case_insensitive(&config.query, &contents)
23+
} else {
24+
search(&config.query, &contents)
25+
};
26+
for line in results {
27+
println!("{line}")
28+
}
29+
Ok(())
30+
}
31+
32+
struct Config {
33+
query: String,
34+
file_path: String,
35+
ignore_case: bool,
36+
}
37+
38+
impl Config {
39+
fn build(args: &[String]) -> Result<Config, &'static str> {
40+
if args.len() < 3 {
41+
return Err("not enough args!");
42+
}
43+
let query = args[1].clone();
44+
let file_path = args[2].clone();
45+
let ignore_case = env::var("IGNORE_CASE").is_ok();
46+
Ok(Config {
47+
query,
48+
file_path,
49+
ignore_case,
50+
})
51+
}
52+
}

0 commit comments

Comments
 (0)