1use serde::{Deserialize, Serialize};
7use strum::{EnumString, Display};
8
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
11pub struct Span {
12 pub start_line: usize,
14 pub start_col: usize,
16 pub end_line: usize,
18 pub end_col: usize,
20}
21
22impl Span {
23 pub fn new(start_line: usize, start_col: usize, end_line: usize, end_col: usize) -> Self {
24 Self {
25 start_line,
26 start_col,
27 end_line,
28 end_col,
29 }
30 }
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, EnumString, Display)]
35#[strum(serialize_all = "PascalCase")]
36pub enum SymbolKind {
37 Function,
38 Class,
39 Struct,
40 Enum,
41 Interface,
42 Trait,
43 Constant,
44 Variable,
45 Method,
46 Module,
47 Namespace,
48 Type,
49 Macro,
50 Property,
51 Event,
52 Import,
53 Export,
54 #[strum(default)]
58 Unknown(String),
59}
60
61#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
63#[serde(rename_all = "lowercase")]
64pub enum Language {
65 Rust,
66 Python,
67 JavaScript,
68 TypeScript,
69 Vue,
70 Svelte,
71 Go,
72 Java,
73 PHP,
74 C,
75 Cpp,
76 CSharp,
77 Ruby,
78 Kotlin,
79 Swift,
80 Zig,
81 Unknown,
82}
83
84impl Language {
85 pub fn from_extension(ext: &str) -> Self {
86 match ext {
87 "rs" => Language::Rust,
88 "py" => Language::Python,
89 "js" | "mjs" | "cjs" | "jsx" => Language::JavaScript,
90 "ts" | "mts" | "cts" | "tsx" => Language::TypeScript,
91 "vue" => Language::Vue,
92 "svelte" => Language::Svelte,
93 "go" => Language::Go,
94 "java" => Language::Java,
95 "php" => Language::PHP,
96 "c" | "h" => Language::C,
97 "cpp" | "cc" | "cxx" | "hpp" | "hxx" | "C" | "H" => Language::Cpp,
98 "cs" => Language::CSharp,
99 "rb" | "rake" | "gemspec" => Language::Ruby,
100 "kt" | "kts" => Language::Kotlin,
101 "swift" => Language::Swift,
102 "zig" => Language::Zig,
103 _ => Language::Unknown,
104 }
105 }
106
107 pub fn is_supported(&self) -> bool {
112 match self {
113 Language::Rust => true,
114 Language::TypeScript => true,
115 Language::JavaScript => true,
116 Language::Vue => true,
117 Language::Svelte => true,
118 Language::Python => true,
119 Language::Go => true,
120 Language::Java => true,
121 Language::PHP => true,
122 Language::C => true,
123 Language::Cpp => true,
124 Language::CSharp => true,
125 Language::Ruby => true,
126 Language::Kotlin => true,
127 Language::Swift => false, Language::Zig => true,
129 Language::Unknown => false,
130 }
131 }
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct SearchResult {
137 pub path: String,
139 pub lang: Language,
141 pub kind: SymbolKind,
143 #[serde(skip_serializing_if = "Option::is_none")]
146 pub symbol: Option<String>,
147 pub span: Span,
149 pub scope: Option<String>,
151 pub preview: String,
153}
154
155impl SearchResult {
156 pub fn new(
157 path: String,
158 lang: Language,
159 kind: SymbolKind,
160 symbol: Option<String>,
161 span: Span,
162 scope: Option<String>,
163 preview: String,
164 ) -> Self {
165 Self {
166 path,
167 lang,
168 kind,
169 symbol,
170 span,
171 scope,
172 preview,
173 }
174 }
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct IndexConfig {
180 pub languages: Vec<Language>,
182 pub include_patterns: Vec<String>,
184 pub exclude_patterns: Vec<String>,
186 pub follow_symlinks: bool,
188 pub max_file_size: usize,
190 pub parallel_threads: usize,
192 pub query_timeout_secs: u64,
194}
195
196impl Default for IndexConfig {
197 fn default() -> Self {
198 Self {
199 languages: vec![],
200 include_patterns: vec![],
201 exclude_patterns: vec![],
202 follow_symlinks: false,
203 max_file_size: 10 * 1024 * 1024, parallel_threads: 0, query_timeout_secs: 30, }
207 }
208}
209
210#[derive(Debug, Clone, Serialize, Deserialize)]
212pub struct IndexStats {
213 pub total_files: usize,
215 pub index_size_bytes: u64,
217 pub last_updated: String,
219 pub files_by_language: std::collections::HashMap<String, usize>,
221 pub lines_by_language: std::collections::HashMap<String, usize>,
223}
224
225#[derive(Debug, Clone, Serialize, Deserialize)]
227pub struct IndexedFile {
228 pub path: String,
230 pub language: String,
232 pub last_indexed: String,
234}
235
236#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
238#[serde(rename_all = "snake_case")]
239pub enum IndexStatus {
240 Fresh,
242 Stale,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
248pub struct IndexWarning {
249 pub reason: String,
251 pub action_required: String,
253 #[serde(skip_serializing_if = "Option::is_none")]
255 pub details: Option<IndexWarningDetails>,
256}
257
258#[derive(Debug, Clone, Serialize, Deserialize)]
260pub struct IndexWarningDetails {
261 #[serde(skip_serializing_if = "Option::is_none")]
263 pub current_branch: Option<String>,
264 #[serde(skip_serializing_if = "Option::is_none")]
266 pub indexed_branch: Option<String>,
267 #[serde(skip_serializing_if = "Option::is_none")]
269 pub current_commit: Option<String>,
270 #[serde(skip_serializing_if = "Option::is_none")]
272 pub indexed_commit: Option<String>,
273}
274
275#[derive(Debug, Clone, Serialize, Deserialize)]
277pub struct QueryResponse {
278 pub status: IndexStatus,
280 pub can_trust_results: bool,
282 #[serde(skip_serializing_if = "Option::is_none")]
284 pub warning: Option<IndexWarning>,
285 pub results: Vec<SearchResult>,
287}