rust_learn/minigrep/src/lib.rs
2024-06-08 15:01:12 +08:00

107 lines
2.7 KiB
Rust
Executable File

use std::error::Error;
use std::fmt;
pub struct Config {
pub query: String,
pub filename: String,
pub sensitive: bool,
}
impl Config {
pub fn new(args: &[String]) -> Result<Config, &'static str> {
if args.len() < 2 {
return Err("args len less then 2");
}
let query = args[0].clone();
let filename = args[1].clone();
let sensitive = std::env::var("CASE_SENSITIVE").is_ok();
Ok(Config {
query,
filename,
sensitive,
})
}
}
pub struct GrepRet {
line: i32,
context: String,
}
impl GrepRet {
fn new(line: i32, context: &str) -> GrepRet {
GrepRet {
line,
context: context.to_string(),
}
}
}
impl fmt::Display for GrepRet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "line:{}: {}", self.line, self.context)
}
}
pub fn run(config: &Config) -> Result<Vec<GrepRet>, Box<dyn Error>> {
let context = std::fs::read_to_string(&config.filename)?;
if config.sensitive {
Ok(search_sensitive(&config.query, &context))
} else {
Ok(search_insensitive(&config.query, &context))
}
}
fn search_sensitive(query: &str, context: &String) -> Vec<GrepRet> {
let mut idx = 0;
let mut result = Vec::new();
for line in context.lines() {
idx += 1;
if line.contains(query) {
result.push(GrepRet::new(idx, line));
}
}
result
}
fn search_insensitive(query: &str, context: &String) -> Vec<GrepRet> {
let mut idx = 0;
let mut result = Vec::new();
for line in context.lines() {
idx += 1;
let lower = line.to_lowercase();
if lower.contains(&query.to_lowercase()) {
result.push(GrepRet::new(idx, line));
}
}
result
}
#[cfg(test)]
pub mod test {
use super::*;
#[test]
fn grep_new1() {
let line = 10;
let context = "zzz";
let grep_ret = GrepRet::new(line, context);
assert_eq!(line, grep_ret.line);
assert_eq!(context, grep_ret.context);
}
#[test]
fn grep_new2() {
let line = 10;
let context = "zzz";
let grep_ret = GrepRet::new(line, context);
assert_ne!(!line, grep_ret.line);
assert_eq!(context, grep_ret.context);
}
#[test]
#[ignore] // cargo test -- --ignored
fn grep_new3() {
let line = 10;
let context = "zzz";
let grep_ret = GrepRet::new(line, context);
assert_ne!(!line, grep_ret.line);
assert_eq!(context, grep_ret.context);
}
}