use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
use roaring::RoaringBitmap;
use crate::index::overlay::OverlayView;
use crate::index::snapshot::{new_snapshot, BaseSegments, IndexSnapshot};
use crate::index::walk::is_binary;
use crate::path::PathIndex;
use crate::{Config, IndexError, SearchMatch, SearchOptions};
pub struct InMemoryIndex {
snapshot: Arc<IndexSnapshot>,
config: Config,
}
impl InMemoryIndex {
pub fn build(files: HashMap<String, Vec<u8>>) -> Result<Self, IndexError> {
let dirty_files: Vec<(PathBuf, Arc<[u8]>)> = files
.iter()
.filter_map(|(rel_str, raw)| {
let content = crate::index::normalize_encoding(raw, false);
if is_binary(&content) {
return None;
}
let path = PathBuf::from(rel_str);
Some((path, Arc::from(content.as_ref())))
})
.collect();
let overlay = OverlayView::build(0, dirty_files)?;
let mut all_paths: Vec<PathBuf> = overlay.docs.iter().map(|d| d.path.clone()).collect();
all_paths.sort_unstable();
all_paths.dedup();
let path_index = PathIndex::build(&all_paths);
let mut overlay_doc_to_file_id = HashMap::new();
for doc in &overlay.docs {
if let Some(fid) = path_index.file_id(&doc.path) {
overlay_doc_to_file_id.insert(doc.doc_id, fid);
}
}
let base = Arc::new(BaseSegments {
segments: vec![],
base_ids: vec![],
base_doc_paths: vec![],
path_doc_ids: HashMap::new(),
});
let snapshot = Arc::new(new_snapshot(
base,
overlay,
RoaringBitmap::new(),
path_index,
Arc::new(Vec::new()),
overlay_doc_to_file_id,
0.10,
));
Ok(InMemoryIndex {
snapshot,
config: Config::default(),
})
}
pub fn search(
&self,
pattern: &str,
opts: &SearchOptions,
) -> Result<Vec<SearchMatch>, IndexError> {
let canonical_root = std::path::Path::new(".");
crate::search::search(
Arc::clone(&self.snapshot),
&self.config,
canonical_root,
pattern,
opts,
)
}
}