1use ahash::AHashMap;
4
5#[derive(Debug, Clone)]
7pub struct QueryProcessor {
8 strategies: AHashMap<String, ProcessingStrategy>,
10}
11
12impl QueryProcessor {
13 pub fn new() -> Self {
15 let mut processor = Self {
16 strategies: AHashMap::new(),
17 };
18
19 processor.register_default_strategies();
21
22 processor
23 }
24
25 pub fn process(&self, query: &str) -> serde_json::Value {
27 let strategy_name = self.analyze_query(query);
29
30 if let Some(strategy) = self.strategies.get(&strategy_name) {
31 self.apply_strategy(strategy, query)
32 } else {
33 serde_json::json!({
35 "query": query,
36 "result": "Processed with default strategy",
37 "metadata": {
38 "strategy": "default",
39 "confidence": 0.5,
40 }
41 })
42 }
43 }
44
45 pub fn register_strategy(&mut self, name: String, strategy: ProcessingStrategy) {
47 self.strategies.insert(name, strategy);
48 }
49
50 fn register_default_strategies(&mut self) {
51 self.strategies.insert(
53 "question".to_string(),
54 ProcessingStrategy {
55 name: "question".to_string(),
56 pattern: r"^(what|who|where|when|why|how)".to_string(),
57 handler: StrategyHandler::Question,
58 },
59 );
60
61 self.strategies.insert(
63 "command".to_string(),
64 ProcessingStrategy {
65 name: "command".to_string(),
66 pattern: r"^(do|create|make|build|generate)".to_string(),
67 handler: StrategyHandler::Command,
68 },
69 );
70
71 self.strategies.insert(
73 "analysis".to_string(),
74 ProcessingStrategy {
75 name: "analysis".to_string(),
76 pattern: r"(analyze|examine|investigate|study)".to_string(),
77 handler: StrategyHandler::Analysis,
78 },
79 );
80 }
81
82 fn analyze_query(&self, query: &str) -> String {
83 let lower_query = query.to_lowercase();
84
85 for (name, strategy) in &self.strategies {
86 if regex_lite::Regex::new(&strategy.pattern)
87 .ok()
88 .map_or(false, |re| re.is_match(&lower_query))
89 {
90 return name.clone();
91 }
92 }
93
94 "default".to_string()
95 }
96
97 fn apply_strategy(&self, strategy: &ProcessingStrategy, query: &str) -> serde_json::Value {
98 match &strategy.handler {
99 StrategyHandler::Question => {
100 serde_json::json!({
101 "query": query,
102 "type": "question",
103 "answer": "This is a question that requires an answer.",
104 "confidence": 0.85,
105 "sources": ["knowledge_base", "context"],
106 })
107 }
108 StrategyHandler::Command => {
109 serde_json::json!({
110 "query": query,
111 "type": "command",
112 "action": "execute",
113 "steps": [
114 "Parse command",
115 "Validate parameters",
116 "Execute action",
117 "Return results",
118 ],
119 "status": "ready",
120 })
121 }
122 StrategyHandler::Analysis => {
123 serde_json::json!({
124 "query": query,
125 "type": "analysis",
126 "findings": {
127 "summary": "Analysis request detected",
128 "key_points": [
129 "Data gathering required",
130 "Pattern analysis needed",
131 "Insights generation",
132 ],
133 },
134 "recommendations": [
135 "Collect relevant data",
136 "Apply analytical framework",
137 "Generate insights report",
138 ],
139 })
140 }
141 StrategyHandler::Custom(handler) => {
142 handler(query)
144 }
145 }
146 }
147}
148
149impl Default for QueryProcessor {
150 fn default() -> Self {
151 Self::new()
152 }
153}
154
155#[derive(Debug, Clone)]
157pub struct ProcessingStrategy {
158 pub name: String,
160
161 pub pattern: String,
163
164 pub handler: StrategyHandler,
166}
167
168#[derive(Debug, Clone)]
170pub enum StrategyHandler {
171 Question,
172 Command,
173 Analysis,
174 Custom(fn(&str) -> serde_json::Value),
175}
176
177mod regex_lite {
179 pub struct Regex {
180 pattern: String,
181 }
182
183 impl Regex {
184 pub fn new(pattern: &str) -> Result<Self, ()> {
185 Ok(Self {
186 pattern: pattern.to_string(),
187 })
188 }
189
190 pub fn is_match(&self, text: &str) -> bool {
191 let cleaned_pattern = self.pattern.trim_start_matches('^').trim_end_matches('$');
193
194 if cleaned_pattern.starts_with('(') && cleaned_pattern.ends_with(')') {
196 let alternatives = cleaned_pattern
197 .trim_start_matches('(')
198 .trim_end_matches(')')
199 .split('|');
200
201 for alt in alternatives {
202 if self.pattern.starts_with('^') {
203 if text.starts_with(alt) {
204 return true;
205 }
206 } else if text.contains(alt) {
207 return true;
208 }
209 }
210 false
211 } else if self.pattern.starts_with('^') {
212 text.starts_with(cleaned_pattern)
213 } else {
214 text.contains(cleaned_pattern)
215 }
216 }
217 }
218}
219
220#[cfg(test)]
221mod tests {
222 use super::*;
223
224 #[test]
225 fn test_query_processor() {
226 let processor = QueryProcessor::new();
227
228 let result = processor.process("What is the weather today?");
230 assert_eq!(result["type"], "question");
231
232 let result = processor.process("Create a new document");
234 assert_eq!(result["type"], "command");
235
236 let result = processor.process("Analyze the sales data");
238 assert_eq!(result["type"], "analysis");
239 }
240}