Skip to main content

ass_editor/utils/search/
trait_impl.rs

1//! `DocumentSearch` implementation for `DocumentSearchImpl`
2//!
3//! Wires the trait methods to the inherent search/index helpers defined in the
4//! sibling modules and holds the index-build and find-replace logic.
5
6use super::engine::DocumentSearchImpl;
7use super::options::{SearchOptions, SearchResult, SearchStats};
8use super::traits::DocumentSearch;
9use crate::core::{EditorDocument, Range, Result};
10
11#[cfg(feature = "std")]
12use std::time::Instant;
13
14#[cfg(not(feature = "std"))]
15#[allow(dead_code)]
16type Instant = u64;
17
18#[cfg(not(feature = "std"))]
19use alloc::vec::Vec;
20
21impl DocumentSearch for DocumentSearchImpl {
22    fn build_index(&mut self, document: &EditorDocument) -> Result<()> {
23        #[cfg(feature = "std")]
24        let _start_time = Instant::now();
25
26        let text = document.text();
27        self.cached_text = text.clone(); // Cache for regex and basic searches
28
29        #[cfg(feature = "search-index")]
30        {
31            let words = self.extract_words(&text);
32
33            // Build FST index
34            let fst = self.build_fst(&words)?;
35            self.word_index = Some(fst);
36
37            // Store word positions
38            self.word_positions.clear();
39            for (word, positions) in words {
40                self.word_positions.insert(word.into_owned(), positions);
41            }
42
43            // Update statistics
44            self.stats.index_size = self.word_positions.len() * 50; // Rough estimate
45        }
46
47        #[cfg(not(feature = "search-index"))]
48        {
49            self.stats.index_size = self.cached_text.len();
50        }
51
52        self.document_version += 1; // Simple increment for cache invalidation
53
54        // Clear cache since index changed
55        self.result_cache.clear();
56
57        Ok(())
58    }
59
60    fn update_index(&mut self, document: &EditorDocument, changes: &[Range]) -> Result<()> {
61        self.update_index_impl(document, changes)
62    }
63
64    fn search<'a>(
65        &'a self,
66        pattern: &str,
67        options: &SearchOptions,
68    ) -> Result<Vec<SearchResult<'a>>> {
69        self.search_impl(pattern, options)
70    }
71
72    fn find_replace<'a>(
73        &'a self,
74        document: &mut EditorDocument,
75        pattern: &str,
76        replacement: &str,
77        options: &SearchOptions,
78    ) -> Result<Vec<SearchResult<'a>>> {
79        let results = self.search(pattern, options)?;
80        let mut replaced = Vec::new();
81
82        // Apply replacements in reverse order to maintain position validity
83        for result in results.iter().rev() {
84            let range = Range::new(result.start, result.end);
85            document.delete(range)?;
86            document.insert(result.start, replacement)?;
87            replaced.push(result.clone());
88        }
89
90        replaced.reverse(); // Restore original order
91        Ok(replaced)
92    }
93
94    fn stats(&self) -> SearchStats {
95        self.stats.clone()
96    }
97
98    fn clear_index(&mut self) {
99        #[cfg(feature = "search-index")]
100        {
101            self.word_index = None;
102            self.word_positions.clear();
103        }
104        self.result_cache.clear();
105        self.cached_text.clear();
106        self.stats.index_size = 0;
107    }
108}