lcpfs 2026.1.102

LCP File System - A ZFS-inspired copy-on-write filesystem for Rust
// Copyright 2025 LunaOS Contributors
// SPDX-License-Identifier: Apache-2.0

//! # Full-Text Search
//!
//! Index file contents for instant search. Like grep but O(1) lookup.
//!
//! ## Overview
//!
//! This module provides full-text indexing and search capabilities for LCPFS,
//! allowing users to search for content across files with BM25 ranking.
//!
//! ## Example
//!
//! ```rust,ignore
//! use lcpfs::fts::{FullTextSearch, SearchOptions};
//!
//! // Index a file
//! FullTextSearch::index_file("pool/data", 42, "/docs/readme.txt", b"Hello world")?;
//!
//! // Search for content
//! let results = FullTextSearch::search("pool/data", "hello", &SearchOptions::default())?;
//! for hit in results {
//!     println!("{}: score {}", hit.path, hit.score);
//! }
//! ```

mod index;
mod ranking;
mod search;
mod tokenizer;
mod types;

pub use index::*;
pub use ranking::*;
pub use search::*;
pub use tokenizer::*;
pub use types::*;

use alloc::string::String;
use alloc::vec::Vec;
use lazy_static::lazy_static;
use spin::Mutex;

lazy_static! {
    /// Global full-text search engine
    static ref FTS_ENGINE: Mutex<FtsEngine> = Mutex::new(FtsEngine::new());
}

/// Full-text search interface
pub struct FullTextSearch;

impl FullTextSearch {
    /// Index a file's content
    ///
    /// # Arguments
    ///
    /// * `dataset` - Dataset name
    /// * `object_id` - Object ID of the file
    /// * `path` - File path
    /// * `content` - File content bytes
    pub fn index_file(
        dataset: &str,
        object_id: u64,
        path: &str,
        content: &[u8],
    ) -> Result<(), IndexError> {
        let mut engine = FTS_ENGINE.lock();
        engine.index_document(dataset, object_id, path, content)
    }

    /// Search for content in a dataset
    ///
    /// # Arguments
    ///
    /// * `dataset` - Dataset to search
    /// * `query` - Search query
    /// * `options` - Search options (limit, fuzzy, etc.)
    pub fn search(
        dataset: &str,
        query: &str,
        options: &SearchOptions,
    ) -> Result<Vec<SearchHit>, IndexError> {
        let engine = FTS_ENGINE.lock();
        engine.search(dataset, query, options)
    }

    /// Rebuild the entire index for a dataset
    pub fn rebuild(dataset: &str) -> Result<IndexStats, IndexError> {
        let mut engine = FTS_ENGINE.lock();
        engine.rebuild(dataset)
    }

    /// Remove a file from the index
    pub fn remove_file(dataset: &str, object_id: u64) -> Result<(), IndexError> {
        let mut engine = FTS_ENGINE.lock();
        engine.remove_document(dataset, object_id)
    }

    /// Get index statistics
    pub fn stats(dataset: &str) -> Result<IndexStats, IndexError> {
        let engine = FTS_ENGINE.lock();
        engine.get_stats(dataset)
    }
}