use crate::Candidate;
use crate::CandidateFilter;
use crate::SearchOutput;
use crate::SearchQuery;
use crate::SearchSeparators;
use crate::SearchStats;
use crate::index::Indexes;
use crate::query::QueryPlanner;
use crate::search::SearchError;
use crate::search::SearchOutcome;
use crate::search::candidates::walk;
use crate::search::request::SearchExecution;
use rayon::prelude::*;
pub struct GrepRequest<'a> {
pub indexes: &'a Indexes,
pub filter: &'a CandidateFilter,
pub output: SearchOutput,
pub separators: &'a SearchSeparators,
pub collect_stats: bool,
}
impl GrepRequest<'_> {
pub fn run(&self, query: &SearchQuery) -> crate::Result<SearchOutcome> {
if query.opts.max_results == Some(0) {
return Err(crate::Error::Search(SearchError::InvalidMaxCount));
}
let spec = query.spec();
let output = self.output;
let raw = QueryPlanner::new(spec).candidates(
self.indexes,
output.candidate_requirement(),
|| walk::collect_candidates(self.filter),
)?;
let candidates: Vec<Candidate> = raw
.into_par_iter()
.filter(|c| c.matches(self.filter))
.collect();
if candidates.is_empty() {
return Ok(SearchOutcome {
matched: false,
stats: self.collect_stats.then_some(SearchStats::default()),
});
}
query.search(&SearchExecution {
candidates,
output,
separators: self.separators,
collect_stats: self.collect_stats,
})
}
}