1pub mod content;
2pub mod path;
3
4use std::collections::{HashMap, HashSet};
5use std::ops::Range;
6use uuid::Uuid;
7
8use crate::model::file::File;
9
10pub use content::ContentSearcher;
11pub use path::PathSearcher;
12
13#[derive(Debug, Clone, Default)]
15pub struct SearchResult {
16 pub id: Uuid,
17 pub filename: String,
18 pub parent_path: String,
19 pub is_folder: bool,
20 pub path_indices: Vec<u32>,
22 pub path_matches: Vec<ContentMatch>,
23 pub content_matches: Vec<ContentMatch>,
25}
26
27#[derive(Debug, Clone)]
29pub enum SearchFilter {
30 Path(String),
32}
33
34#[derive(Debug, Clone)]
36pub struct ContentMatch {
37 pub range: Range<usize>,
39 pub exact: bool,
41}
42
43use crate::Lb;
44
45impl Lb {
46 pub async fn path_searcher(&self) -> PathSearcher {
47 PathSearcher::new(self).await
48 }
49}
50
51pub(crate) fn build_descendants(files: &[File]) -> HashMap<Uuid, Vec<Uuid>> {
54 let parent_of: HashMap<Uuid, Uuid> = files.iter().map(|f| (f.id, f.parent)).collect();
55
56 let mut descendants: HashMap<Uuid, Vec<Uuid>> = HashMap::new();
57 for f in files {
58 let mut node = f.id;
59 while let Some(&parent) = parent_of.get(&node) {
60 if parent == node {
61 break; }
63 descendants.entry(parent).or_default().push(f.id);
64 node = parent;
65 }
66 }
67
68 descendants
69}
70
71pub(crate) fn resolve_filter(
74 filter: Option<SearchFilter>, path_to_id: &HashMap<String, Uuid>,
75 descendants: &HashMap<Uuid, Vec<Uuid>>,
76) -> Option<HashSet<Uuid>> {
77 filter.map(|SearchFilter::Path(path)| {
78 path_to_id
79 .get(&path)
80 .and_then(|id| descendants.get(id))
81 .map(|ids| ids.iter().copied().collect())
82 .unwrap_or_default()
83 })
84}