use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Config {
pub chunking: ChunkingConfig,
pub qr: QrConfig,
pub video: VideoConfig,
pub ml: MlConfig,
pub search: SearchConfig,
pub storage: StorageConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChunkingConfig {
pub chunk_size: usize,
pub overlap: usize,
pub min_chunk_size: usize,
pub max_chunk_size: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QrConfig {
pub version: Option<i16>,
pub error_correction: ErrorCorrectionLevel,
pub box_size: u32,
pub border: u32,
pub fill_color: String,
pub back_color: String,
pub enable_compression: bool,
pub compression_threshold: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ErrorCorrectionLevel {
Low, Medium, Quartile, High, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VideoConfig {
pub codec: String,
pub fps: f64,
pub frame_width: u32,
pub frame_height: u32,
pub quality_params: HashMap<String, String>,
pub hardware_acceleration: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MlConfig {
pub model_name: String,
pub device: String,
pub max_sequence_length: usize,
pub batch_size: usize,
pub cache_dir: Option<String>,
pub quantization: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchConfig {
pub engine: String,
pub hnsw: HnswConfig,
pub max_results: usize,
pub min_score_threshold: f32,
pub enable_reranking: bool,
pub cache_size: usize,
pub max_workers: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HnswConfig {
pub max_connections: usize,
pub ef_construction: usize,
pub ef_search: usize,
pub seed: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StorageConfig {
pub database_path: Option<String>,
pub enable_wal_mode: bool,
pub cache_size: i64,
pub foreign_keys: bool,
pub synchronous: String,
pub index_format_version: u32,
}
impl Default for ChunkingConfig {
fn default() -> Self {
Self {
chunk_size: 1024,
overlap: 32,
min_chunk_size: 100,
max_chunk_size: 4096,
}
}
}
impl Default for QrConfig {
fn default() -> Self {
Self {
version: None, error_correction: ErrorCorrectionLevel::Medium,
box_size: 10,
border: 4,
fill_color: "black".to_string(),
back_color: "white".to_string(),
enable_compression: true,
compression_threshold: 100,
}
}
}
impl Default for VideoConfig {
fn default() -> Self {
let mut quality_params = HashMap::new();
quality_params.insert("crf".to_string(), "28".to_string());
quality_params.insert("preset".to_string(), "slower".to_string());
quality_params.insert("tune".to_string(), "zerolatency".to_string()); quality_params.insert("profile".to_string(), "main".to_string());
quality_params.insert("pix_fmt".to_string(), "yuv420p".to_string());
Self {
codec: "libx265".to_string(), fps: 30.0, frame_width: 256, frame_height: 256, quality_params,
hardware_acceleration: true,
}
}
}
impl Default for MlConfig {
fn default() -> Self {
Self {
model_name: "sentence-transformers/all-MiniLM-L6-v2".to_string(),
device: "auto".to_string(),
max_sequence_length: 512,
batch_size: 32,
cache_dir: None,
quantization: false,
}
}
}
impl Default for SearchConfig {
fn default() -> Self {
Self {
engine: "auto".to_string(),
hnsw: HnswConfig::default(),
max_results: 100,
min_score_threshold: 0.0,
enable_reranking: false,
cache_size: 1000,
max_workers: 4,
}
}
}
impl Default for HnswConfig {
fn default() -> Self {
Self {
max_connections: 16,
ef_construction: 200,
ef_search: 50,
seed: None,
}
}
}
impl Default for StorageConfig {
fn default() -> Self {
Self {
database_path: None,
enable_wal_mode: true,
cache_size: 10000, foreign_keys: true,
synchronous: "NORMAL".to_string(),
index_format_version: 1,
}
}
}
impl From<ErrorCorrectionLevel> for qrcode::EcLevel {
fn from(level: ErrorCorrectionLevel) -> Self {
match level {
ErrorCorrectionLevel::Low => qrcode::EcLevel::L,
ErrorCorrectionLevel::Medium => qrcode::EcLevel::M,
ErrorCorrectionLevel::Quartile => qrcode::EcLevel::Q,
ErrorCorrectionLevel::High => qrcode::EcLevel::H,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = Config::default();
assert_eq!(config.chunking.chunk_size, 1024);
assert_eq!(config.qr.box_size, 10);
assert_eq!(config.video.fps, 30.0);
assert_eq!(
config.ml.model_name,
"sentence-transformers/all-MiniLM-L6-v2"
);
}
#[test]
fn test_config_serialization() {
let config = Config::default();
let json = serde_json::to_string(&config).unwrap();
let deserialized: Config = serde_json::from_str(&json).unwrap();
assert_eq!(config.chunking.chunk_size, deserialized.chunking.chunk_size);
assert_eq!(config.ml.model_name, deserialized.ml.model_name);
}
#[test]
fn test_error_correction_conversion() {
let level = ErrorCorrectionLevel::High;
let qr_level: qrcode::EcLevel = level.into();
assert_eq!(qr_level, qrcode::EcLevel::H);
}
}