Skip to main content

orbok_core/
search_scope.rs

1//! Which files a search may return (RFC-060 §7).
2//!
3//! Plain data, shared by the query layer (`orbok-db` builds the SQL) and
4//! the search engine (`orbok-search` fills it in from the UI's filters and
5//! chosen folder). Both halves must agree, and a scope applied anywhere
6//! but the query is not a scope: post-filtering shrinks the result set
7//! below the requested limit and makes "no results" ambiguous
8//! (RFC-041 §25.5).
9
10/// One folder restriction: a registered source, optionally a subfolder of
11/// it, and whether nested folders count.
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct FolderScope {
14    pub source_id: String,
15    /// Task 113: the canonical path of a folder **inside** the source, when
16    /// the search is limited to that subfolder. `None` searches the source
17    /// itself. A file is inside when this is a path-component prefix of its
18    /// path (`orbok_core::folder_cover`); "folder only" is then counted from
19    /// this folder, not from the source.
20    pub limit_path: Option<String>,
21    /// `false` restricts to files sitting directly in the folder (the
22    /// source, or `limit_path` when it is set; RFC-045 §6.3's "folder only").
23    pub include_subfolders: bool,
24}
25
26/// The scope of one search. Empty means unrestricted.
27#[derive(Debug, Clone, Default, PartialEq, Eq)]
28pub struct SearchScope {
29    /// Lowercased file extensions, without the dot. Empty means every
30    /// kind; the UI's kind filters expand to these.
31    pub extensions: Vec<String>,
32    pub folder: Option<FolderScope>,
33}
34
35impl SearchScope {
36    /// Whether this scope restricts anything at all.
37    pub fn is_unrestricted(&self) -> bool {
38        self.extensions.is_empty() && self.folder.is_none()
39    }
40}