Skip to content

Instantly share code, notes, and snippets.

@christianscott
Created July 8, 2019 11:00
Show Gist options
  • Save christianscott/249596551afdfcdc1ddc0241097f5ccc to your computer and use it in GitHub Desktop.
Save christianscott/249596551afdfcdc1ddc0241097f5ccc to your computer and use it in GitHub Desktop.
Shitty grep implementation
use std::env;
use std::fs;
use std::io;
use std::path::Path;
use std::str;
fn main() -> io::Result<()> {
let args: Vec<String> = env::args().collect();
let pattern = &args[1];
let path = &args[2];
grep(Path::new(&path), pattern)?;
Ok(())
}
pub fn grep(dir: &Path, pattern: &str) -> Result<(), io::Error> {
if !dir.is_dir() {
return Ok(());
}
let entries = fs::read_dir(dir)?;
for entry in entries {
let entry = entry?;
let path = entry.path();
match path.file_name() {
Some(filename) => {
let contents = fs::read_to_string(&path)?;
println!("got the contents");
let filename = filename.to_str().expect("invalid filename");
if let Some(index) = contents.find(pattern) {
print_match(filename, &contents.as_bytes(), pattern, index);
}
}
None => {
grep(&path, pattern)?;
}
}
}
Ok(())
}
const NEWLINE_BYTE: u8 = 0xA;
fn print_match<'a>(filename: &str, contents: &[u8], _pattern: &str, index: usize) {
let mut line_start = 0;
let mut current = index;
while current > 0 {
current -= 1;
if contents[current] == NEWLINE_BYTE {
line_start = current;
break;
}
}
let mut line_end = contents.len();
current = index;
while current < contents.len() {
current += 1;
if contents[current] == NEWLINE_BYTE {
line_end = current;
break;
}
}
if let Ok(line) = String::from_utf8(contents[line_start..line_end].to_vec()) {
println!("{}:{}", filename, line);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment