1pub mod allocator;
7pub mod buffer_pool;
8pub mod scanner;
9pub mod simd;
10pub mod simd_zero_copy;
11pub mod simple;
12pub mod sonic;
13pub mod value;
14pub mod zero_copy;
15
16pub use allocator::{AllocatorBackend, AllocatorStats, SimdAllocator, global_allocator};
17pub use buffer_pool::{
18 BufferPool, BufferSize, PoolConfig, PooledBuffer, SimdType, global_buffer_pool,
19};
20pub use scanner::{JsonScanner, ScanResult, StringLocation};
21pub use simd_zero_copy::{
22 SimdParseResult, SimdParsingStats, SimdZeroCopyConfig, SimdZeroCopyParser,
23};
24pub use simple::{ParseConfig, ParseStats, SimpleParser};
25pub use sonic::{LazyFrame, SonicConfig, SonicParser};
26pub use value::{JsonValue, LazyArray, LazyObject};
27pub use zero_copy::{IncrementalParser, LazyJsonValue, LazyParser, MemoryUsage, ZeroCopyParser};
28
29use crate::{Result, SemanticMeta};
30
31pub struct Parser {
33 sonic: SonicParser,
34 simple: SimpleParser,
35 zero_copy_simd: Option<SimdZeroCopyParser<'static>>,
36 use_sonic: bool,
37 use_zero_copy: bool,
38}
39
40impl Parser {
41 pub fn new() -> Self {
43 Self {
44 sonic: SonicParser::new(),
45 simple: SimpleParser::new(),
46 zero_copy_simd: None, use_sonic: true,
48 use_zero_copy: true, }
50 }
51
52 pub fn with_config(config: ParseConfig) -> Self {
54 let sonic_config = SonicConfig {
55 detect_semantics: config.detect_semantics,
56 max_input_size: config.max_size_mb * 1024 * 1024,
57 };
58
59 Self {
60 sonic: SonicParser::with_config(sonic_config),
61 simple: SimpleParser::with_config(config),
62 zero_copy_simd: None, use_sonic: true,
64 use_zero_copy: true,
65 }
66 }
67
68 pub fn with_serde_fallback() -> Self {
70 Self {
71 sonic: SonicParser::new(),
72 simple: SimpleParser::new(),
73 zero_copy_simd: None,
74 use_sonic: false,
75 use_zero_copy: false, }
77 }
78
79 pub fn zero_copy_optimized() -> Self {
81 Self {
82 sonic: SonicParser::new(),
83 simple: SimpleParser::new(),
84 zero_copy_simd: None, use_sonic: false, use_zero_copy: true,
87 }
88 }
89
90 pub fn parse(&self, input: &[u8]) -> Result<crate::Frame> {
92 if self.use_sonic {
93 match self.sonic.parse(input) {
95 Ok(frame) => Ok(frame),
96 Err(_) => {
97 self.simple.parse(input)
99 }
100 }
101 } else {
102 self.simple.parse(input)
103 }
104 }
105
106 pub fn parse_with_semantics(
108 &self,
109 input: &[u8],
110 semantics: &SemanticMeta,
111 ) -> Result<crate::Frame> {
112 if self.use_sonic {
113 self.simple.parse_with_semantics(input, semantics)
116 } else {
117 self.simple.parse_with_semantics(input, semantics)
118 }
119 }
120
121 pub fn stats(&self) -> ParseStats {
123 if self.use_sonic {
124 ParseStats::default()
126 } else {
127 self.simple.stats()
128 }
129 }
130}
131
132impl Default for Parser {
133 fn default() -> Self {
134 Self::new()
135 }
136}
137
138#[derive(Debug, Clone, Copy, PartialEq)]
140pub enum ValueType {
141 Object,
142 Array,
143 String,
144 Number,
145 Boolean,
146 Null,
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152
153 #[test]
154 fn test_parser_creation() {
155 let parser = Parser::new();
156 assert_eq!(parser.stats().total_parses, 0);
157 }
158
159 #[test]
160 fn test_simple_parsing() {
161 let parser = Parser::new();
162 let input = br#"{"hello": "world"}"#;
163 let result = parser.parse(input);
164 assert!(result.is_ok());
165
166 let frame = result.unwrap();
167 assert_eq!(frame.payload.len(), input.len());
169 }
170
171 #[test]
172 fn test_numeric_array_parsing() {
173 let parser = Parser::new();
174 let input = b"[1.0, 2.0, 3.0, 4.0]";
175 let result = parser.parse(input);
176 assert!(result.is_ok());
177 }
178
179 #[test]
180 fn test_semantic_parsing() {
181 let parser = Parser::new();
182 let input = b"[1, 2, 3, 4]";
183
184 let semantics = crate::SemanticMeta::new(crate::semantic::SemanticType::NumericArray {
185 dtype: crate::semantic::NumericDType::I32,
186 length: Some(4),
187 });
188
189 let result = parser.parse_with_semantics(input, &semantics);
190 assert!(result.is_ok());
191 }
192
193 #[test]
194 fn test_custom_config() {
195 let config = ParseConfig {
196 detect_semantics: false,
197 max_size_mb: 50,
198 stream_large_arrays: false,
199 stream_threshold: 500,
200 };
201
202 let parser = Parser::with_config(config);
203 let input = br#"{"test": "data"}"#;
204 let result = parser.parse(input);
205 assert!(result.is_ok());
206 }
207}