1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9#[derive(Debug, Clone, Serialize, Deserialize, Default)]
11pub struct Config {
12 pub chunking: ChunkingConfig,
14
15 pub qr: QrConfig,
17
18 pub video: VideoConfig,
20
21 pub ml: MlConfig,
23
24 pub search: SearchConfig,
26
27 pub storage: StorageConfig,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct ChunkingConfig {
34 pub chunk_size: usize,
36
37 pub overlap: usize,
39
40 pub min_chunk_size: usize,
42
43 pub max_chunk_size: usize,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct QrConfig {
50 pub version: Option<i16>,
52
53 pub error_correction: ErrorCorrectionLevel,
55
56 pub box_size: u32,
58
59 pub border: u32,
61
62 pub fill_color: String,
64
65 pub back_color: String,
67
68 pub enable_compression: bool,
70
71 pub compression_threshold: usize,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
77pub enum ErrorCorrectionLevel {
78 Low, Medium, Quartile, High, }
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct VideoConfig {
87 pub codec: String,
89
90 pub fps: f64,
92
93 pub frame_width: u32,
95
96 pub frame_height: u32,
98
99 pub quality_params: HashMap<String, String>,
101
102 pub hardware_acceleration: bool,
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct MlConfig {
109 pub model_name: String,
111
112 pub device: String,
114
115 pub max_sequence_length: usize,
117
118 pub batch_size: usize,
120
121 pub cache_dir: Option<String>,
123
124 pub quantization: bool,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
130pub struct SearchConfig {
131 pub engine: String,
133
134 pub hnsw: HnswConfig,
136
137 pub max_results: usize,
139
140 pub min_score_threshold: f32,
142
143 pub enable_reranking: bool,
145
146 pub cache_size: usize,
148
149 pub max_workers: usize,
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize)]
155pub struct HnswConfig {
156 pub max_connections: usize,
158
159 pub ef_construction: usize,
161
162 pub ef_search: usize,
164
165 pub seed: Option<u64>,
167}
168
169#[derive(Debug, Clone, Serialize, Deserialize)]
171pub struct StorageConfig {
172 pub database_path: Option<String>,
174
175 pub enable_wal_mode: bool,
177
178 pub cache_size: i64,
180
181 pub foreign_keys: bool,
183
184 pub synchronous: String,
186
187 pub index_format_version: u32,
189}
190
191impl Default for ChunkingConfig {
192 fn default() -> Self {
193 Self {
194 chunk_size: 1024,
195 overlap: 32,
196 min_chunk_size: 100,
197 max_chunk_size: 4096,
198 }
199 }
200}
201
202impl Default for QrConfig {
203 fn default() -> Self {
204 Self {
205 version: None, error_correction: ErrorCorrectionLevel::Medium,
207 box_size: 10,
208 border: 4,
209 fill_color: "black".to_string(),
210 back_color: "white".to_string(),
211 enable_compression: true,
212 compression_threshold: 100,
213 }
214 }
215}
216
217impl Default for VideoConfig {
218 fn default() -> Self {
219 let mut quality_params = HashMap::new();
220 quality_params.insert("crf".to_string(), "28".to_string());
222 quality_params.insert("preset".to_string(), "slower".to_string());
223 quality_params.insert("tune".to_string(), "zerolatency".to_string()); quality_params.insert("profile".to_string(), "main".to_string());
225 quality_params.insert("pix_fmt".to_string(), "yuv420p".to_string());
226
227 Self {
228 codec: "libx265".to_string(), fps: 30.0, frame_width: 256, frame_height: 256, quality_params,
233 hardware_acceleration: true,
234 }
235 }
236}
237
238impl Default for MlConfig {
239 fn default() -> Self {
240 Self {
241 model_name: "sentence-transformers/all-MiniLM-L6-v2".to_string(),
242 device: "auto".to_string(),
243 max_sequence_length: 512,
244 batch_size: 32,
245 cache_dir: None,
246 quantization: false,
247 }
248 }
249}
250
251impl Default for SearchConfig {
252 fn default() -> Self {
253 Self {
254 engine: "auto".to_string(),
255 hnsw: HnswConfig::default(),
256 max_results: 100,
257 min_score_threshold: 0.0,
258 enable_reranking: false,
259 cache_size: 1000,
260 max_workers: 4,
261 }
262 }
263}
264
265impl Default for HnswConfig {
266 fn default() -> Self {
267 Self {
268 max_connections: 16,
269 ef_construction: 200,
270 ef_search: 50,
271 seed: None,
272 }
273 }
274}
275
276impl Default for StorageConfig {
277 fn default() -> Self {
278 Self {
279 database_path: None,
280 enable_wal_mode: true,
281 cache_size: 10000, foreign_keys: true,
283 synchronous: "NORMAL".to_string(),
284 index_format_version: 1,
285 }
286 }
287}
288
289impl From<ErrorCorrectionLevel> for qrcode::EcLevel {
291 fn from(level: ErrorCorrectionLevel) -> Self {
292 match level {
293 ErrorCorrectionLevel::Low => qrcode::EcLevel::L,
294 ErrorCorrectionLevel::Medium => qrcode::EcLevel::M,
295 ErrorCorrectionLevel::Quartile => qrcode::EcLevel::Q,
296 ErrorCorrectionLevel::High => qrcode::EcLevel::H,
297 }
298 }
299}
300
301#[cfg(test)]
302mod tests {
303 use super::*;
304
305 #[test]
306 fn test_default_config() {
307 let config = Config::default();
308 assert_eq!(config.chunking.chunk_size, 1024);
309 assert_eq!(config.qr.box_size, 10);
310 assert_eq!(config.video.fps, 30.0);
311 assert_eq!(
312 config.ml.model_name,
313 "sentence-transformers/all-MiniLM-L6-v2"
314 );
315 }
316
317 #[test]
318 fn test_config_serialization() {
319 let config = Config::default();
320 let json = serde_json::to_string(&config).unwrap();
321 let deserialized: Config = serde_json::from_str(&json).unwrap();
322
323 assert_eq!(config.chunking.chunk_size, deserialized.chunking.chunk_size);
324 assert_eq!(config.ml.model_name, deserialized.ml.model_name);
325 }
326
327 #[test]
328 fn test_error_correction_conversion() {
329 let level = ErrorCorrectionLevel::High;
330 let qr_level: qrcode::EcLevel = level.into();
331 assert_eq!(qr_level, qrcode::EcLevel::H);
332 }
333}