1use serde::{Deserialize, Serialize};
4use std::path::PathBuf;
5use uuid::Uuid;
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
9pub struct WorkspaceId(pub Uuid);
10
11impl WorkspaceId {
12 pub fn new() -> Self {
14 Self(Uuid::new_v4())
15 }
16
17 pub fn from_uuid(uuid: Uuid) -> Self {
19 Self(uuid)
20 }
21
22 pub fn as_uuid(&self) -> &Uuid {
24 &self.0
25 }
26}
27
28impl Default for WorkspaceId {
29 fn default() -> Self {
30 Self::new()
31 }
32}
33
34impl std::fmt::Display for WorkspaceId {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 write!(f, "{}", self.0)
37 }
38}
39
40#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
42pub struct DocumentId(pub Uuid);
43
44impl DocumentId {
45 pub fn new() -> Self {
47 Self(Uuid::new_v4())
48 }
49}
50
51impl Default for DocumentId {
52 fn default() -> Self {
53 Self::new()
54 }
55}
56
57#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
59pub struct ChunkId(pub Uuid);
60
61impl ChunkId {
62 pub fn new() -> Self {
64 Self(Uuid::new_v4())
65 }
66}
67
68impl Default for ChunkId {
69 fn default() -> Self {
70 Self::new()
71 }
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct Document {
77 pub id: DocumentId,
79 pub relative_path: PathBuf,
81 pub absolute_path: PathBuf,
83 pub language: Language,
85 pub content_hash: String,
87 pub size_bytes: u64,
89 pub modified_at: chrono::DateTime<chrono::Utc>,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct Chunk {
96 pub id: ChunkId,
98 pub document_id: DocumentId,
100 pub content: String,
102 pub chunk_type: ChunkType,
104 pub start_line: u32,
106 pub end_line: u32,
108 pub start_byte: usize,
110 pub end_byte: usize,
112 pub symbol_name: Option<String>,
114 pub parent_symbol: Option<String>,
116}
117
118#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
120pub enum ChunkType {
121 Function,
123 Class,
125 Struct,
127 Enum,
129 Interface,
131 Module,
133 Imports,
135 Constant,
137 TypeDef,
139 Implementation,
141 Block,
143 Comment,
145}
146
147#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
149pub enum Language {
150 Rust,
152 Python,
154 JavaScript,
156 TypeScript,
158 Go,
160 C,
162 Cpp,
164 Java,
166 Unknown,
168}
169
170impl Language {
171 pub fn from_extension(ext: &str) -> Self {
173 match ext.to_lowercase().as_str() {
174 "rs" => Language::Rust,
175 "py" | "pyw" | "pyi" => Language::Python,
176 "js" | "mjs" | "cjs" => Language::JavaScript,
177 "ts" | "mts" | "cts" => Language::TypeScript,
178 "tsx" | "jsx" => Language::TypeScript, "go" => Language::Go,
180 "c" | "h" => Language::C,
181 "cpp" | "cc" | "cxx" | "hpp" | "hxx" | "hh" => Language::Cpp,
182 "java" => Language::Java,
183 _ => Language::Unknown,
184 }
185 }
186
187 pub fn extensions(&self) -> &'static [&'static str] {
189 match self {
190 Language::Rust => &["rs"],
191 Language::Python => &["py", "pyw", "pyi"],
192 Language::JavaScript => &["js", "mjs", "cjs", "jsx"],
193 Language::TypeScript => &["ts", "mts", "cts", "tsx"],
194 Language::Go => &["go"],
195 Language::C => &["c", "h"],
196 Language::Cpp => &["cpp", "cc", "cxx", "hpp", "hxx", "hh"],
197 Language::Java => &["java"],
198 Language::Unknown => &[],
199 }
200 }
201
202 pub fn as_str(&self) -> &'static str {
204 match self {
205 Language::Rust => "rust",
206 Language::Python => "python",
207 Language::JavaScript => "javascript",
208 Language::TypeScript => "typescript",
209 Language::Go => "go",
210 Language::C => "c",
211 Language::Cpp => "cpp",
212 Language::Java => "java",
213 Language::Unknown => "unknown",
214 }
215 }
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
220pub struct SearchResult {
221 pub chunk: Chunk,
223 pub document: Document,
225 pub score: f32,
227 pub match_type: MatchType,
229 pub highlights: Vec<Highlight>,
231}
232
233#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
235pub enum MatchType {
236 Lexical,
238 Semantic,
240 Hybrid,
242}
243
244#[derive(Debug, Clone, Serialize, Deserialize)]
246pub struct Highlight {
247 pub start: usize,
249 pub end: usize,
251 pub text: String,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize)]
257pub struct IndexProgress {
258 pub phase: IndexPhase,
260 pub processed: usize,
262 pub total: usize,
264 pub current_file: Option<PathBuf>,
266 pub eta_seconds: Option<f64>,
268}
269
270impl IndexProgress {
271 pub fn percentage(&self) -> f64 {
273 if self.total == 0 {
274 0.0
275 } else {
276 (self.processed as f64 / self.total as f64) * 100.0
277 }
278 }
279}
280
281#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
283pub enum IndexPhase {
284 Scanning,
286 Parsing,
288 Embedding,
290 Indexing,
292 Persisting,
294 Complete,
296}
297
298#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct WorkspaceStats {
301 pub workspace_id: WorkspaceId,
303 pub root_path: PathBuf,
305 pub document_count: usize,
307 pub chunk_count: usize,
309 pub total_bytes: u64,
311 pub index_size_bytes: u64,
313 pub created_at: chrono::DateTime<chrono::Utc>,
315 pub updated_at: chrono::DateTime<chrono::Utc>,
317 pub language_stats: Vec<LanguageStats>,
319}
320
321#[derive(Debug, Clone, Serialize, Deserialize)]
323pub struct LanguageStats {
324 pub language: Language,
326 pub file_count: usize,
328 pub chunk_count: usize,
330 pub total_bytes: u64,
332}