minigrep_flict 0.1.0

Simplest text-in-file search engine from rust book
Documentation
//! # Mini Grep
//!
//! `minigrep` this is the simplest text-in-file search engine
//! 
use std::env;
use std::error::Error;
use std::fs;

pub struct Config<'a> {
    pub query: &'a String,
    pub filename: &'a String,
    pub case_sensitive: bool,
}

impl<'a> Config<'a> {
    pub fn new(args: &[String]) -> Result<Config, &'static str> {
        if args.len() < 3 {
            return Err("Not enough arguments!");
        } else {
            let query: &String = &args[1];
            let filename: &String = &args[2];
            let case_sensitive = env::var("CASE_INSENSITIVE").is_err();

            Ok(Config {
                query,
                filename,
                case_sensitive,
            })
        }
    }
}

pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
    let contents: String = fs::read_to_string(config.filename)?;

    println!("Searching for: '{}' in {}", config.query, config.filename);

    let results = if config.case_sensitive {
        search_case_sensative(config.query, &contents)
    } else {
        search_case_insensative(config.query, &contents)
    };
    println!("========");
    println!("Results:");
    println!("========");
    if results.len() > 0 {
        for (key, value) in results.iter().enumerate() {
            println!("{}: {}", key, value);
        }
    } else {
        println!("Program doesn't found any words!")
    }

    Ok(())
}
/// Search words in lines with sensative mode
///
/// # Examples
///
///
/// ```
/// let query = "duct";
/// let contents = "\
/// Rust:
/// safe, fast, productive.
/// Pick three.";
///
/// assert_eq!(vec!["safe, fast, productive."], minigrep_flict::search_case_sensative(query, contents));  
/// ```
pub fn search_case_sensative<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    contents
        .lines()
        .filter(|line| line.contains(query))
        .collect()
}

/// Search words in lines with insensative mode
///
/// # Examples
///
///
/// ```
/// let query = "rust";
/// let contents = "\
/// Rust:
/// safe, fast, productive.
/// Pick three.";
///
/// assert_eq!(vec!["Rust:"], minigrep_flict::search_case_insensative(query, contents));                 
/// ```
pub fn search_case_insensative<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    let lower_query = query.to_lowercase();
    contents
        .lines()
        .filter(|line| line.to_lowercase().contains(&lower_query))
        .collect()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn search_s_result() {
        let query = "duct";
        let contents = "\
Rust:
safe, fast, productive.
Pick three.";

        assert_eq!(
            vec!["safe, fast, productive."],
            search_case_sensative(query, contents)
        );
    }
    #[test]
    fn search_in_result() {
        let query = "rust";
        let contents = "\
Rust:
safe, fast, productive.
Pick three.";

        assert_eq!(vec!["Rust:"], search_case_insensative(query, contents));
    }

    #[test]
    #[should_panic]
    fn search_result() {
        let query = "rust";
        let contents = "\
Rust:
safe, fast, productive.
Pick three.";

        assert_eq!(vec!["Rust:"], search_case_sensative(query, contents));
    }
}