Skip to main content

fmf_core\query/
mod.rs

1//! Query engine: text → AST → compiled matchers → parallel scan →
2//! materialized, sort-ordered result (docs/ARCHITECTURE.md).
3//!
4//! Syntax (core):
5//! `space`=AND, `|`=OR (weakest), `!`=NOT, `"..."`=phrase, `*`/`?` wildcards
6//! (match the whole name), a `\` inside a term switches it to path matching,
7//! and the filters `ext:`, `path:`, `size:`, `dm:`, `regex:`, `file:`,
8//! `folder:`.
9
10mod ast;
11mod compile;
12mod dates;
13mod exec;
14mod matchers;
15mod memo;
16mod subsume;
17mod sweep;
18
19pub use ast::{Ast, ParseError, Term, parse};
20pub use compile::{CaseMode, CompileError, CompiledQuery, compile, compile_whole_regex};
21#[cfg(windows)]
22pub use dates::WindowsLocalResolver;
23pub use dates::{DateResolver, UtcResolver};
24pub(crate) use exec::refine;
25pub use exec::{SearchMetrics, SearchResult, search};
26pub use fmf_contract::options::RegexScope;
27pub use memo::{derived_cache_bytes, prewarm};
28pub(crate) use subsume::subsumes;
29
30use crate::index::SortKey;
31
32/// Per-query options controlling sort order, case handling, visibility, and
33/// whole-query regex mode — the engine-side form the wire options convert into.
34#[derive(Clone, Copy, Debug, PartialEq, Eq)]
35pub struct QueryOptions {
36    /// Which column the materialized result is sorted by (name, size, date…).
37    pub sort: SortKey,
38    /// Sort descending when set, ascending otherwise.
39    pub desc: bool,
40    /// Case-sensitivity policy applied to matchers (smart/sensitive/insensitive).
41    pub case: CaseMode,
42    /// Hidden/system entries (and everything under such branches) are
43    /// skipped unless this is set — the UI toggle maps straight here.
44    pub include_hidden_system: bool,
45    /// Treat the whole query text as one regex (`regex_mode` bit0) — the
46    /// engine skips parsing and compiles a single `regex_scope` matcher.
47    pub regex_mode: bool,
48    /// Which haystack the whole-query regex runs against (ignored unless
49    /// `regex_mode`).
50    pub regex_scope: RegexScope,
51}
52
53impl Default for QueryOptions {
54    fn default() -> Self {
55        Self {
56            sort: SortKey::Name,
57            desc: false,
58            case: CaseMode::Smart,
59            include_hidden_system: false,
60            regex_mode: false,
61            regex_scope: RegexScope::Name,
62        }
63    }
64}
65
66/// The single wire→engine options conversion — both boundaries (FFI
67/// `fmf_query` and pipe dispatch) go through this (ADR-0018). `regex_mode`
68/// is a packed u32: bit0 = whole-query regex on, bit1 = scope (0 name /
69/// 1 path).
70impl From<fmf_contract::pod::FmfQueryOptions> for QueryOptions {
71    fn from(o: fmf_contract::pod::FmfQueryOptions) -> Self {
72        Self {
73            sort: SortKey::from_u32(o.sort),
74            desc: o.desc != 0,
75            case: CaseMode::from_u32(o.case_mode),
76            include_hidden_system: o.include_hidden_system != 0,
77            regex_mode: o.regex_mode & 0b1 != 0,
78            regex_scope: RegexScope::from_u32((o.regex_mode >> 1) & 0b1),
79        }
80    }
81}