use super::options::{SearchOptions, SearchResult, SearchStats};
#[cfg(feature = "std")]
use std::collections::HashMap;
#[cfg(not(feature = "std"))]
use hashbrown::HashMap;
#[cfg(not(feature = "std"))]
use alloc::{format, string::String, vec::Vec};
#[cfg(feature = "search-index")]
use crate::core::Position;
#[cfg(feature = "search-index")]
use fst::Set;
#[derive(Debug)]
pub struct DocumentSearchImpl {
#[cfg(feature = "search-index")]
pub(super) word_index: Option<Set<Vec<u8>>>,
#[cfg(feature = "search-index")]
pub(super) word_positions: HashMap<String, Vec<Position>>,
pub(super) document_version: u64,
pub(super) result_cache: HashMap<String, Vec<SearchResult<'static>>>,
pub(super) max_cache_entries: usize,
pub(super) stats: SearchStats,
pub(super) cached_text: String,
}
impl DocumentSearchImpl {
pub fn new() -> Self {
Self {
#[cfg(feature = "search-index")]
word_index: None,
#[cfg(feature = "search-index")]
word_positions: HashMap::new(),
document_version: 0,
result_cache: HashMap::new(),
max_cache_entries: 100,
stats: SearchStats {
match_count: 0,
search_time_us: 0,
hit_limit: false,
index_size: 0,
},
cached_text: String::new(),
}
}
pub fn set_cache_size(&mut self, size: usize) {
self.max_cache_entries = size;
self.trim_cache();
}
fn trim_cache(&mut self) {
if self.result_cache.len() > self.max_cache_entries {
let keys_to_remove: Vec<String> = self
.result_cache
.keys()
.take(self.result_cache.len() / 2)
.cloned()
.collect();
for key in keys_to_remove {
self.result_cache.remove(&key);
}
}
}
pub(super) fn cache_key(&self, pattern: &str, options: &SearchOptions) -> String {
format!(
"{}|{}|{}|{}|{:?}",
pattern,
options.case_sensitive,
options.whole_words,
options.max_results,
options.scope
)
}
}
impl Default for DocumentSearchImpl {
fn default() -> Self {
Self::new()
}
}