pjson_rs/
config.rs

1//! Global configuration for PJS Core library
2//!
3//! This module provides centralized configuration for all components,
4//! replacing hardcoded constants with configurable values.
5
6use crate::compression::CompressionConfig;
7
8/// Global configuration for PJS library components
9#[derive(Debug, Clone, Default)]
10pub struct PjsConfig {
11    /// Configuration for compression algorithms
12    pub compression: CompressionConfig,
13    /// Configuration for parsers
14    pub parser: ParserConfig,
15    /// Configuration for streaming
16    pub streaming: StreamingConfig,
17    /// Configuration for SIMD operations
18    pub simd: SimdConfig,
19}
20
21/// Configuration for JSON parsers
22#[derive(Debug, Clone)]
23pub struct ParserConfig {
24    /// Maximum input size in MB
25    pub max_input_size_mb: usize,
26    /// Buffer initial capacity in bytes
27    pub buffer_initial_capacity: usize,
28    /// SIMD minimum size threshold
29    pub simd_min_size: usize,
30    /// Enable semantic type detection
31    pub enable_semantics: bool,
32}
33
34/// Configuration for streaming operations
35#[derive(Debug, Clone)]
36pub struct StreamingConfig {
37    /// Maximum frame size in bytes
38    pub max_frame_size: usize,
39    /// Default chunk size for processing
40    pub default_chunk_size: usize,
41    /// Timeout for operations in milliseconds
42    pub operation_timeout_ms: u64,
43    /// Maximum bandwidth in bytes per second
44    pub max_bandwidth_bps: u64,
45}
46
47/// Configuration for SIMD acceleration
48#[derive(Debug, Clone)]
49pub struct SimdConfig {
50    /// Batch size for SIMD operations
51    pub batch_size: usize,
52    /// Initial capacity for SIMD buffers
53    pub initial_capacity: usize,
54    /// AVX-512 alignment size in bytes
55    pub avx512_alignment: usize,
56    /// Chunk size for vectorized operations
57    pub vectorized_chunk_size: usize,
58    /// Enable statistics collection
59    pub enable_stats: bool,
60}
61
62
63impl Default for ParserConfig {
64    fn default() -> Self {
65        Self {
66            max_input_size_mb: 100,
67            buffer_initial_capacity: 8192, // 8KB
68            simd_min_size: 4096, // 4KB
69            enable_semantics: true,
70        }
71    }
72}
73
74impl Default for StreamingConfig {
75    fn default() -> Self {
76        Self {
77            max_frame_size: 64 * 1024, // 64KB
78            default_chunk_size: 1024,
79            operation_timeout_ms: 5000, // 5 seconds
80            max_bandwidth_bps: 1_000_000, // 1MB/s
81        }
82    }
83}
84
85impl Default for SimdConfig {
86    fn default() -> Self {
87        Self {
88            batch_size: 100,
89            initial_capacity: 8192, // 8KB
90            avx512_alignment: 64,
91            vectorized_chunk_size: 32,
92            enable_stats: false,
93        }
94    }
95}
96
97/// Configuration profiles for different use cases
98impl PjsConfig {
99    /// Configuration optimized for low latency
100    pub fn low_latency() -> Self {
101        Self {
102            compression: CompressionConfig::default(),
103            parser: ParserConfig {
104                max_input_size_mb: 10,
105                buffer_initial_capacity: 4096, // 4KB
106                simd_min_size: 2048, // 2KB
107                enable_semantics: false, // Disable for speed
108            },
109            streaming: StreamingConfig {
110                max_frame_size: 16 * 1024, // 16KB
111                default_chunk_size: 512,
112                operation_timeout_ms: 1000, // 1 second
113                max_bandwidth_bps: 10_000_000, // 10MB/s
114            },
115            simd: SimdConfig {
116                batch_size: 50,
117                initial_capacity: 4096, // 4KB
118                avx512_alignment: 64,
119                vectorized_chunk_size: 16,
120                enable_stats: false,
121            },
122        }
123    }
124
125    /// Configuration optimized for high throughput
126    pub fn high_throughput() -> Self {
127        Self {
128            compression: CompressionConfig::default(),
129            parser: ParserConfig {
130                max_input_size_mb: 1000, // 1GB
131                buffer_initial_capacity: 32768, // 32KB
132                simd_min_size: 8192, // 8KB
133                enable_semantics: true,
134            },
135            streaming: StreamingConfig {
136                max_frame_size: 256 * 1024, // 256KB
137                default_chunk_size: 4096,
138                operation_timeout_ms: 30000, // 30 seconds
139                max_bandwidth_bps: 100_000_000, // 100MB/s
140            },
141            simd: SimdConfig {
142                batch_size: 500,
143                initial_capacity: 32768, // 32KB
144                avx512_alignment: 64,
145                vectorized_chunk_size: 64,
146                enable_stats: true,
147            },
148        }
149    }
150
151    /// Configuration optimized for mobile/constrained devices
152    pub fn mobile() -> Self {
153        Self {
154            compression: CompressionConfig {
155                min_array_length: 1,
156                min_string_length: 2,
157                min_frequency_count: 1,
158                uuid_compression_potential: 0.5,
159                string_dict_threshold: 25.0, // Lower threshold
160                delta_threshold: 15.0, // Lower threshold
161                min_delta_potential: 0.2,
162                run_length_threshold: 10.0, // Lower threshold
163                min_compression_potential: 0.3,
164                min_numeric_sequence_size: 2,
165            },
166            parser: ParserConfig {
167                max_input_size_mb: 10,
168                buffer_initial_capacity: 2048, // 2KB
169                simd_min_size: 1024, // 1KB
170                enable_semantics: false,
171            },
172            streaming: StreamingConfig {
173                max_frame_size: 8 * 1024, // 8KB
174                default_chunk_size: 256,
175                operation_timeout_ms: 10000, // 10 seconds
176                max_bandwidth_bps: 100_000, // 100KB/s
177            },
178            simd: SimdConfig {
179                batch_size: 25,
180                initial_capacity: 2048, // 2KB
181                avx512_alignment: 32, // Smaller alignment
182                vectorized_chunk_size: 8,
183                enable_stats: false,
184            },
185        }
186    }
187}
188
189#[cfg(test)]
190mod tests {
191    use super::*;
192
193    #[test]
194    fn test_default_config() {
195        let config = PjsConfig::default();
196        assert_eq!(config.parser.max_input_size_mb, 100);
197        assert_eq!(config.streaming.max_frame_size, 64 * 1024);
198        assert_eq!(config.simd.batch_size, 100);
199    }
200
201    #[test]
202    fn test_low_latency_profile() {
203        let config = PjsConfig::low_latency();
204        assert_eq!(config.streaming.max_frame_size, 16 * 1024);
205        assert!(!config.parser.enable_semantics);
206        assert_eq!(config.streaming.operation_timeout_ms, 1000);
207    }
208
209    #[test]
210    fn test_high_throughput_profile() {
211        let config = PjsConfig::high_throughput();
212        assert_eq!(config.streaming.max_frame_size, 256 * 1024);
213        assert!(config.parser.enable_semantics);
214        assert!(config.simd.enable_stats);
215    }
216
217    #[test]
218    fn test_mobile_profile() {
219        let config = PjsConfig::mobile();
220        assert_eq!(config.streaming.max_frame_size, 8 * 1024);
221        assert_eq!(config.compression.string_dict_threshold, 25.0);
222        assert_eq!(config.simd.vectorized_chunk_size, 8);
223    }
224
225    #[test]
226    fn test_compression_with_custom_config() {
227        use crate::compression::{SchemaAnalyzer, CompressionConfig};
228        use serde_json::json;
229
230        // Create custom compression config with lower thresholds
231        let compression_config = CompressionConfig {
232            string_dict_threshold: 10.0, // Lower threshold for testing
233            min_frequency_count: 1,
234            ..Default::default()
235        };
236
237        let mut analyzer = SchemaAnalyzer::with_config(compression_config);
238        
239        // Test data that should trigger dictionary compression with low threshold
240        let data = json!({
241            "users": [
242                {"status": "active", "role": "user"},
243                {"status": "active", "role": "user"}
244            ]
245        });
246
247        let strategy = analyzer.analyze(&data).unwrap();
248        
249        // With lower threshold, should detect dictionary compression opportunity
250        match strategy {
251            crate::compression::CompressionStrategy::Dictionary { .. } | 
252            crate::compression::CompressionStrategy::Hybrid { .. } => {
253                // Expected with low threshold
254            },
255            _ => {
256                // Also acceptable, depends on specific data characteristics
257            }
258        }
259    }
260}