1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
use std::fs::File; use std::io::{BufReader, BufRead}; use std::path::PathBuf; use anyhow::{Result, Context}; pub fn find_matches<'a>(path: &PathBuf, pattern: &'a str) -> Result<impl Iterator<Item=String> + 'a> { let file = File::open(path) .with_context(|| format!("could not open file `{}`", path.display()))?; let results = BufReader::new(file) .lines() // Convert Iterator<Item=Result<T>> into Iterator<Item=T>: // https://stackoverflow.com/a/36371890/3592218 // There are two *different* solutions: `filter_map` and `scan`. // >>> `filter_map`: .filter_map(|x| x.ok()) // >>> `scan`: // .scan((), |_, x| x.ok()) .filter(move |line| line.contains(pattern)); Ok(results) }