From b10c01f40c99b4af2ca85a3da969b6af1c6ebd6f Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Fri, 1 Feb 2019 16:33:01 -0500 Subject: [PATCH] Add iterator/closure updated version of minigrep example --- .idea/misc.xml | 1 + .idea/rust.iml | 5 +++ .idea/workspace.xml | 91 ++++++++++++++++++++++++++++--------- minigrep_v2/Cargo.toml | 7 +++ minigrep_v2/src/lib.rs | 99 +++++++++++++++++++++++++++++++++++++++++ minigrep_v2/src/main.rs | 17 +++++++ 6 files changed, 198 insertions(+), 22 deletions(-) create mode 100644 minigrep_v2/Cargo.toml create mode 100644 minigrep_v2/src/lib.rs create mode 100644 minigrep_v2/src/main.rs diff --git a/.idea/misc.xml b/.idea/misc.xml index 9afac53..b80d65b 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -22,6 +22,7 @@ + diff --git a/.idea/rust.iml b/.idea/rust.iml index 06f6986..3f12527 100644 --- a/.idea/rust.iml +++ b/.idea/rust.iml @@ -86,6 +86,10 @@ + + + + @@ -99,6 +103,7 @@ + diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 2ce6851..c72ff77 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,6 +2,8 @@ + + - - + + - - - - - - + + + + + + + + + + + + + + + + + + + + @@ -85,6 +101,8 @@ @@ -118,12 +136,17 @@ - + - + + + + + + @@ -157,7 +180,7 @@ - + @@ -185,7 +208,7 @@ - + - + @@ -263,11 +286,11 @@ + - @@ -296,13 +319,16 @@ + + + - - + + @@ -310,7 +336,7 @@ - + @@ -318,7 +344,7 @@ - + @@ -630,8 +656,8 @@ - - + + @@ -639,5 +665,26 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/minigrep_v2/Cargo.toml b/minigrep_v2/Cargo.toml new file mode 100644 index 0000000..65d0fb1 --- /dev/null +++ b/minigrep_v2/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "minigrep_v2" +version = "0.1.0" +authors = ["Timothy Warren "] +edition = "2018" + +[dependencies] diff --git a/minigrep_v2/src/lib.rs b/minigrep_v2/src/lib.rs new file mode 100644 index 0000000..ea89a74 --- /dev/null +++ b/minigrep_v2/src/lib.rs @@ -0,0 +1,99 @@ +use std::env; +use std::error::Error; +use std::fs; + +pub struct Config { + pub query: String, + pub filename: String, + pub case_sensitive: bool, +} + +impl Config { + pub fn new(mut args: std::env::Args) -> Result { + args.next(); // Skip the program's name + + let query = match args.next() { + Some(arg) => arg, + None => return Err("Didn't get a query string"), + }; + + let filename = match args.next() { + Some(arg) => arg, + None => return Err("Didn't get a file name"), + }; + + let case_sensitive = env::var("CASE_INSENSITIVE").is_err(); + + Ok(Config { query, filename, case_sensitive }) + } +} + +pub fn run(config: Config) -> Result<(), Box> { + // The ? operator passes the error back to the caller. + let contents = fs::read_to_string(config.filename)?; + + let results = if config.case_sensitive { + search(&config.query, &contents) + } else { + search_case_insensitive(&config.query, &contents) + }; + + for line in results { + println!("{}", line); + } + + Ok(()) +} + +fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { + contents.lines() + .filter(|line| line.contains(query)) + .collect() +} + +fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { + let query = query.to_lowercase(); + + contents.lines() + .filter(|line| { + line.to_lowercase() + .as_str() + .contains(query.as_str()) + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn case_sensitive() { + let query = "duct"; + let contents = "\ +Rust: +safe, fast, productive. +Pick three. +Duct tape."; + + assert_eq!( + vec!["safe, fast, productive."], + search(query, contents) + ); + } + + #[test] + fn case_insensitive() { + let query = "rUsT"; + let contents = "\ +Rust: +safe, fast, productive. +Pick three. +Trust me."; + + assert_eq!( + vec!["Rust:", "Trust me."], + search_case_insensitive(query, contents) + ); + } +} diff --git a/minigrep_v2/src/main.rs b/minigrep_v2/src/main.rs new file mode 100644 index 0000000..1e79fdd --- /dev/null +++ b/minigrep_v2/src/main.rs @@ -0,0 +1,17 @@ +use std::env; +use std::process; + +use minigrep_v2; +use minigrep_v2::Config; + +fn main() { + let config = Config::new(env::args()).unwrap_or_else(|err| { + eprintln!("Problem parsing arguments: {}", err); + process::exit(1); + }); + + if let Err(e) = minigrep_v2::run(config) { + eprintln!("Application error: {}", e); + process::exit(1); + } +}