1use crate::{
7 config::SecurityConfig,
8 domain::{DomainError, DomainResult},
9 parser::ValueType,
10 security::SecurityValidator,
11};
12use std::{marker::PhantomData, str::from_utf8};
13
14pub trait LazyParser<'a> {
19 type Output;
21 type Error;
23
24 fn parse_lazy(&mut self, input: &'a [u8]) -> Result<Self::Output, Self::Error>;
26
27 fn remaining(&self) -> &'a [u8];
29
30 fn is_complete(&self) -> bool;
32
33 fn reset(&mut self);
35}
36
37pub struct ZeroCopyParser<'a> {
39 input: &'a [u8],
40 position: usize,
41 depth: usize,
42 validator: SecurityValidator,
43 _phantom: PhantomData<&'a ()>,
44}
45
46impl<'a> ZeroCopyParser<'a> {
47 pub fn new() -> Self {
49 Self {
50 input: &[],
51 position: 0,
52 depth: 0,
53 validator: SecurityValidator::default(),
54 _phantom: PhantomData,
55 }
56 }
57
58 pub fn with_security_config(security_config: SecurityConfig) -> Self {
60 Self {
61 input: &[],
62 position: 0,
63 depth: 0,
64 validator: SecurityValidator::new(security_config),
65 _phantom: PhantomData,
66 }
67 }
68
69 pub fn parse_value(&mut self) -> DomainResult<LazyJsonValue<'a>> {
71 self.skip_whitespace();
72
73 if self.position >= self.input.len() {
74 return Err(DomainError::InvalidInput(
75 "Unexpected end of input".to_string(),
76 ));
77 }
78
79 let ch = self.input[self.position];
80 match ch {
81 b'"' => self.parse_string(),
82 b'{' => self.parse_object(),
83 b'[' => self.parse_array(),
84 b't' | b'f' => self.parse_boolean(),
85 b'n' => self.parse_null(),
86 b'-' | b'0'..=b'9' => self.parse_number(),
87 _ => {
88 let ch_char = ch as char;
89 Err(DomainError::InvalidInput(format!(
90 "Unexpected character: {ch_char}"
91 )))
92 }
93 }
94 }
95
96 fn parse_string(&mut self) -> DomainResult<LazyJsonValue<'a>> {
98 if self.position >= self.input.len() || self.input[self.position] != b'"' {
99 return Err(DomainError::InvalidInput("Expected '\"'".to_string()));
100 }
101
102 let start = self.position + 1; self.position += 1;
104
105 while self.position < self.input.len() {
107 match self.input[self.position] {
108 b'"' => {
109 let string_slice = &self.input[start..self.position];
110 self.position += 1; if string_slice.contains(&b'\\') {
114 let unescaped = self.unescape_string(string_slice)?;
116 return Ok(LazyJsonValue::StringOwned(unescaped));
117 } else {
118 return Ok(LazyJsonValue::StringBorrowed(string_slice));
120 }
121 }
122 b'\\' => {
123 self.position += 2;
125 }
126 _ => {
127 self.position += 1;
128 }
129 }
130 }
131
132 Err(DomainError::InvalidInput("Unterminated string".to_string()))
133 }
134
135 fn parse_object(&mut self) -> DomainResult<LazyJsonValue<'a>> {
137 self.validator
138 .validate_json_depth(self.depth + 1)
139 .map_err(|e| DomainError::SecurityViolation(e.to_string()))?;
140
141 if self.position >= self.input.len() || self.input[self.position] != b'{' {
142 return Err(DomainError::InvalidInput("Expected '{'".to_string()));
143 }
144
145 let start = self.position;
146 self.position += 1; self.depth += 1;
148
149 self.skip_whitespace();
150
151 if self.position < self.input.len() && self.input[self.position] == b'}' {
153 self.position += 1;
154 self.depth -= 1;
155 return Ok(LazyJsonValue::ObjectSlice(
156 &self.input[start..self.position],
157 ));
158 }
159
160 let mut first = true;
161 while self.position < self.input.len() && self.input[self.position] != b'}' {
162 if !first {
163 self.expect_char(b',')?;
164 self.skip_whitespace();
165 }
166 first = false;
167
168 let _key = self.parse_value()?;
170 self.skip_whitespace();
171 self.expect_char(b':')?;
172 self.skip_whitespace();
173
174 let _value = self.parse_value()?;
176 self.skip_whitespace();
177 }
178
179 self.expect_char(b'}')?;
180 self.depth -= 1;
181
182 Ok(LazyJsonValue::ObjectSlice(
183 &self.input[start..self.position],
184 ))
185 }
186
187 fn parse_array(&mut self) -> DomainResult<LazyJsonValue<'a>> {
189 self.validator
190 .validate_json_depth(self.depth + 1)
191 .map_err(|e| DomainError::SecurityViolation(e.to_string()))?;
192
193 if self.position >= self.input.len() || self.input[self.position] != b'[' {
194 return Err(DomainError::InvalidInput("Expected '['".to_string()));
195 }
196
197 let start = self.position;
198 self.position += 1; self.depth += 1;
200
201 self.skip_whitespace();
202
203 if self.position < self.input.len() && self.input[self.position] == b']' {
205 self.position += 1;
206 self.depth -= 1;
207 return Ok(LazyJsonValue::ArraySlice(&self.input[start..self.position]));
208 }
209
210 let mut first = true;
211 while self.position < self.input.len() && self.input[self.position] != b']' {
212 if !first {
213 self.expect_char(b',')?;
214 self.skip_whitespace();
215 }
216 first = false;
217
218 let _element = self.parse_value()?;
220 self.skip_whitespace();
221 }
222
223 self.expect_char(b']')?;
224 self.depth -= 1;
225
226 Ok(LazyJsonValue::ArraySlice(&self.input[start..self.position]))
227 }
228
229 fn parse_boolean(&mut self) -> DomainResult<LazyJsonValue<'a>> {
231 if self.position + 4 <= self.input.len()
232 && &self.input[self.position..self.position + 4] == b"true"
233 {
234 self.position += 4;
235 Ok(LazyJsonValue::Boolean(true))
236 } else if self.position + 5 <= self.input.len()
237 && &self.input[self.position..self.position + 5] == b"false"
238 {
239 self.position += 5;
240 Ok(LazyJsonValue::Boolean(false))
241 } else {
242 Err(DomainError::InvalidInput(
243 "Invalid boolean value".to_string(),
244 ))
245 }
246 }
247
248 fn parse_null(&mut self) -> DomainResult<LazyJsonValue<'a>> {
250 if self.position + 4 <= self.input.len()
251 && &self.input[self.position..self.position + 4] == b"null"
252 {
253 self.position += 4;
254 Ok(LazyJsonValue::Null)
255 } else {
256 Err(DomainError::InvalidInput("Invalid null value".to_string()))
257 }
258 }
259
260 fn parse_number(&mut self) -> DomainResult<LazyJsonValue<'a>> {
262 let start = self.position;
263
264 if self.input[self.position] == b'-' {
266 self.position += 1;
267 }
268
269 if self.position >= self.input.len() {
271 return Err(DomainError::InvalidInput("Invalid number".to_string()));
272 }
273
274 if self.input[self.position] == b'0' {
275 self.position += 1;
276 } else if self.input[self.position].is_ascii_digit() {
277 while self.position < self.input.len() && self.input[self.position].is_ascii_digit() {
278 self.position += 1;
279 }
280 } else {
281 return Err(DomainError::InvalidInput("Invalid number".to_string()));
282 }
283
284 if self.position < self.input.len() && self.input[self.position] == b'.' {
286 self.position += 1;
287 if self.position >= self.input.len() || !self.input[self.position].is_ascii_digit() {
288 return Err(DomainError::InvalidInput(
289 "Invalid number: missing digits after decimal".to_string(),
290 ));
291 }
292 while self.position < self.input.len() && self.input[self.position].is_ascii_digit() {
293 self.position += 1;
294 }
295 }
296
297 if self.position < self.input.len()
299 && (self.input[self.position] == b'e' || self.input[self.position] == b'E')
300 {
301 self.position += 1;
302 if self.position < self.input.len()
303 && (self.input[self.position] == b'+' || self.input[self.position] == b'-')
304 {
305 self.position += 1;
306 }
307 if self.position >= self.input.len() || !self.input[self.position].is_ascii_digit() {
308 return Err(DomainError::InvalidInput(
309 "Invalid number: missing digits in exponent".to_string(),
310 ));
311 }
312 while self.position < self.input.len() && self.input[self.position].is_ascii_digit() {
313 self.position += 1;
314 }
315 }
316
317 let number_slice = &self.input[start..self.position];
318 Ok(LazyJsonValue::NumberSlice(number_slice))
319 }
320
321 fn skip_whitespace(&mut self) {
323 while self.position < self.input.len() {
324 match self.input[self.position] {
325 b' ' | b'\t' | b'\n' | b'\r' => {
326 self.position += 1;
327 }
328 _ => break,
329 }
330 }
331 }
332
333 fn expect_char(&mut self, ch: u8) -> DomainResult<()> {
335 if self.position >= self.input.len() || self.input[self.position] != ch {
336 let ch_char = ch as char;
337 return Err(DomainError::InvalidInput(format!("Expected '{ch_char}'")));
338 }
339 self.position += 1;
340 Ok(())
341 }
342
343 fn unescape_string(&self, input: &[u8]) -> DomainResult<String> {
345 let mut result = Vec::with_capacity(input.len());
346 let mut i = 0;
347
348 while i < input.len() {
349 if input[i] == b'\\' && i + 1 < input.len() {
350 match input[i + 1] {
351 b'"' => result.push(b'"'),
352 b'\\' => result.push(b'\\'),
353 b'/' => result.push(b'/'),
354 b'b' => result.push(b'\x08'),
355 b'f' => result.push(b'\x0C'),
356 b'n' => result.push(b'\n'),
357 b'r' => result.push(b'\r'),
358 b't' => result.push(b'\t'),
359 b'u' => {
360 let high = Self::parse_hex4(input, i + 2)?;
361 i += 6;
362
363 let codepoint = if (0xD800..=0xDBFF).contains(&high) {
364 if i + 1 >= input.len() || input[i] != b'\\' || input[i + 1] != b'u' {
366 return Err(DomainError::InvalidInput(
367 "Unpaired high surrogate in unicode escape".to_string(),
368 ));
369 }
370 let low = Self::parse_hex4(input, i + 2)?;
371 if !(0xDC00..=0xDFFF).contains(&low) {
372 return Err(DomainError::InvalidInput(
373 "High surrogate not followed by low surrogate".to_string(),
374 ));
375 }
376 i += 6;
377 0x10000 + (high - 0xD800) * 0x400 + (low - 0xDC00)
378 } else if (0xDC00..=0xDFFF).contains(&high) {
379 return Err(DomainError::InvalidInput(
380 "Unpaired low surrogate in unicode escape".to_string(),
381 ));
382 } else {
383 high
384 };
385
386 let ch = char::from_u32(codepoint).ok_or_else(|| {
387 DomainError::InvalidInput(
388 "Invalid unicode codepoint in escape sequence".to_string(),
389 )
390 })?;
391 let mut buf = [0u8; 4];
392 result.extend_from_slice(ch.encode_utf8(&mut buf).as_bytes());
393 continue;
394 }
395 _ => {
396 return Err(DomainError::InvalidInput(
397 "Invalid escape sequence".to_string(),
398 ));
399 }
400 }
401 i += 2;
402 } else {
403 result.push(input[i]);
404 i += 1;
405 }
406 }
407
408 String::from_utf8(result)
409 .map_err(|e| DomainError::InvalidInput(format!("Invalid UTF-8: {e}")))
410 }
411
412 fn parse_hex4(input: &[u8], pos: usize) -> DomainResult<u32> {
414 let hex = input
415 .get(pos..pos + 4)
416 .ok_or_else(|| DomainError::InvalidInput("Invalid unicode escape".to_string()))?;
417 if !hex.iter().all(u8::is_ascii_hexdigit) {
421 return Err(DomainError::InvalidInput(
422 "Invalid unicode escape".to_string(),
423 ));
424 }
425 let hex_str = std::str::from_utf8(hex)
426 .map_err(|_| DomainError::InvalidInput("Invalid unicode escape".to_string()))?;
427 u32::from_str_radix(hex_str, 16)
428 .map_err(|_| DomainError::InvalidInput("Invalid unicode escape".to_string()))
429 }
430}
431
432impl<'a> LazyParser<'a> for ZeroCopyParser<'a> {
433 type Output = LazyJsonValue<'a>;
434 type Error = DomainError;
435
436 fn parse_lazy(&mut self, input: &'a [u8]) -> Result<Self::Output, Self::Error> {
437 self.validator
439 .validate_input_size(input.len())
440 .map_err(|e| DomainError::SecurityViolation(e.to_string()))?;
441
442 self.input = input;
443 self.position = 0;
444 self.depth = 0;
445
446 self.parse_value()
447 }
448
449 fn remaining(&self) -> &'a [u8] {
450 if self.position < self.input.len() {
451 &self.input[self.position..]
452 } else {
453 &[]
454 }
455 }
456
457 fn is_complete(&self) -> bool {
458 self.position >= self.input.len()
459 }
460
461 fn reset(&mut self) {
462 self.input = &[];
463 self.position = 0;
464 self.depth = 0;
465 }
466}
467
468#[derive(Debug, Clone, PartialEq)]
470pub enum LazyJsonValue<'a> {
471 StringBorrowed(&'a [u8]),
473 StringOwned(String),
475 NumberSlice(&'a [u8]),
477 Boolean(bool),
479 Null,
481 ObjectSlice(&'a [u8]),
483 ArraySlice(&'a [u8]),
485}
486
487impl<'a> LazyJsonValue<'a> {
488 pub fn value_type(&self) -> ValueType {
490 match self {
491 LazyJsonValue::StringBorrowed(_) | LazyJsonValue::StringOwned(_) => ValueType::String,
492 LazyJsonValue::NumberSlice(_) => ValueType::Number,
493 LazyJsonValue::Boolean(_) => ValueType::Boolean,
494 LazyJsonValue::Null => ValueType::Null,
495 LazyJsonValue::ObjectSlice(_) => ValueType::Object,
496 LazyJsonValue::ArraySlice(_) => ValueType::Array,
497 }
498 }
499
500 pub fn to_string_lossy(&self) -> String {
502 match self {
503 LazyJsonValue::StringBorrowed(bytes) => String::from_utf8_lossy(bytes).to_string(),
504 LazyJsonValue::StringOwned(s) => s.clone(),
505 LazyJsonValue::NumberSlice(bytes) => String::from_utf8_lossy(bytes).to_string(),
506 LazyJsonValue::Boolean(b) => b.to_string(),
507 LazyJsonValue::Null => "null".to_string(),
508 LazyJsonValue::ObjectSlice(bytes) => String::from_utf8_lossy(bytes).to_string(),
509 LazyJsonValue::ArraySlice(bytes) => String::from_utf8_lossy(bytes).to_string(),
510 }
511 }
512
513 pub fn as_str(&self) -> DomainResult<&str> {
515 match self {
516 LazyJsonValue::StringBorrowed(bytes) => from_utf8(bytes)
517 .map_err(|e| DomainError::InvalidInput(format!("Invalid UTF-8: {e}"))),
518 LazyJsonValue::StringOwned(s) => Ok(s.as_str()),
519 _ => Err(DomainError::InvalidInput(
520 "Value is not a string".to_string(),
521 )),
522 }
523 }
524
525 pub fn as_number(&self) -> DomainResult<f64> {
527 match self {
528 LazyJsonValue::NumberSlice(bytes) => {
529 let s = from_utf8(bytes)
530 .map_err(|e| DomainError::InvalidInput(format!("Invalid UTF-8: {e}")))?;
531 s.parse::<f64>()
532 .map_err(|e| DomainError::InvalidInput(format!("Invalid number: {e}")))
533 }
534 _ => Err(DomainError::InvalidInput(
535 "Value is not a number".to_string(),
536 )),
537 }
538 }
539
540 pub fn as_boolean(&self) -> DomainResult<bool> {
542 match self {
543 LazyJsonValue::Boolean(b) => Ok(*b),
544 _ => Err(DomainError::InvalidInput(
545 "Value is not a boolean".to_string(),
546 )),
547 }
548 }
549
550 pub fn is_null(&self) -> bool {
552 matches!(self, LazyJsonValue::Null)
553 }
554
555 pub fn as_bytes(&self) -> Option<&'a [u8]> {
557 match self {
558 LazyJsonValue::StringBorrowed(bytes) => Some(bytes),
559 LazyJsonValue::NumberSlice(bytes) => Some(bytes),
560 LazyJsonValue::ObjectSlice(bytes) => Some(bytes),
561 LazyJsonValue::ArraySlice(bytes) => Some(bytes),
562 _ => None,
563 }
564 }
565
566 pub fn memory_usage(&self) -> MemoryUsage {
568 match self {
569 LazyJsonValue::StringBorrowed(bytes) => MemoryUsage {
570 allocated_bytes: 0,
571 referenced_bytes: bytes.len(),
572 },
573 LazyJsonValue::StringOwned(s) => MemoryUsage {
574 allocated_bytes: s.len(),
575 referenced_bytes: 0,
576 },
577 LazyJsonValue::NumberSlice(bytes) => MemoryUsage {
578 allocated_bytes: 0,
579 referenced_bytes: bytes.len(),
580 },
581 LazyJsonValue::Boolean(val) => MemoryUsage {
582 allocated_bytes: 0,
583 referenced_bytes: if *val { 4 } else { 5 }, },
585 LazyJsonValue::Null => MemoryUsage {
586 allocated_bytes: 0,
587 referenced_bytes: 4, },
589 LazyJsonValue::ObjectSlice(bytes) => MemoryUsage {
590 allocated_bytes: 0,
591 referenced_bytes: bytes.len(),
592 },
593 LazyJsonValue::ArraySlice(bytes) => MemoryUsage {
594 allocated_bytes: 0,
595 referenced_bytes: bytes.len(),
596 },
597 }
598 }
599}
600
601#[derive(Debug, Clone, PartialEq)]
603pub struct MemoryUsage {
604 pub allocated_bytes: usize,
606 pub referenced_bytes: usize,
608}
609
610impl MemoryUsage {
611 pub fn total(&self) -> usize {
613 self.allocated_bytes + self.referenced_bytes
614 }
615
616 pub fn efficiency(&self) -> f64 {
618 if self.total() == 0 {
619 1.0
620 } else {
621 self.referenced_bytes as f64 / self.total() as f64
622 }
623 }
624}
625
626pub struct IncrementalParser<'a> {
628 buffer: Vec<u8>,
629 _phantom: std::marker::PhantomData<&'a ()>,
630}
631
632impl<'a> Default for IncrementalParser<'a> {
633 fn default() -> Self {
634 Self::new()
635 }
636}
637
638impl<'a> IncrementalParser<'a> {
639 pub fn new() -> Self {
641 Self {
642 buffer: Vec::with_capacity(8192), _phantom: std::marker::PhantomData,
644 }
645 }
646
647 pub fn feed(&mut self, data: &[u8]) -> DomainResult<()> {
649 self.buffer.extend_from_slice(data);
650 Ok(())
651 }
652
653 pub fn parse_available(&mut self) -> DomainResult<Vec<LazyJsonValue<'_>>> {
655 if !self.buffer.is_empty() {
658 let mut parser = ZeroCopyParser::new();
659 match parser.parse_lazy(&self.buffer) {
660 Ok(_value) => {
661 self.buffer.clear();
664 Ok(vec![])
665 }
666 Err(_e) => Ok(vec![]), }
668 } else {
669 Ok(vec![])
670 }
671 }
672
673 pub fn has_complete_value(&self) -> bool {
675 !self.buffer.is_empty()
677 }
678}
679
680impl<'a> Default for ZeroCopyParser<'a> {
681 fn default() -> Self {
682 Self::new()
683 }
684}
685
686#[cfg(test)]
687mod tests {
688 use super::*;
689
690 #[test]
691 fn test_parse_string() {
692 let mut parser = ZeroCopyParser::new();
693 let input = br#""hello world""#;
694
695 let result = parser.parse_lazy(input).unwrap();
696 match result {
697 LazyJsonValue::StringBorrowed(bytes) => {
698 assert_eq!(bytes, b"hello world");
699 }
700 _ => panic!("Expected string"),
701 }
702 }
703
704 #[test]
705 fn test_parse_escaped_string() {
706 let mut parser = ZeroCopyParser::new();
707 let input = br#""hello \"world\"""#;
708
709 let result = parser.parse_lazy(input).unwrap();
710 match result {
711 LazyJsonValue::StringOwned(s) => {
712 assert_eq!(s, "hello \"world\"");
713 }
714 _ => panic!("Expected owned string due to escapes"),
715 }
716 }
717
718 #[test]
719 fn test_parse_number() {
720 let mut parser = ZeroCopyParser::new();
721 let input = b"123.45";
722
723 let result = parser.parse_lazy(input).unwrap();
724 match result {
725 LazyJsonValue::NumberSlice(bytes) => {
726 assert_eq!(bytes, b"123.45");
727 assert_eq!(result.as_number().unwrap(), 123.45);
728 }
729 _ => panic!("Expected number"),
730 }
731 }
732
733 #[test]
734 fn test_parse_boolean() {
735 let mut parser = ZeroCopyParser::new();
736
737 let result = parser.parse_lazy(b"true").unwrap();
738 assert_eq!(result, LazyJsonValue::Boolean(true));
739
740 parser.reset();
741 let result = parser.parse_lazy(b"false").unwrap();
742 assert_eq!(result, LazyJsonValue::Boolean(false));
743 }
744
745 #[test]
746 fn test_parse_null() {
747 let mut parser = ZeroCopyParser::new();
748 let result = parser.parse_lazy(b"null").unwrap();
749 assert_eq!(result, LazyJsonValue::Null);
750 assert!(result.is_null());
751 }
752
753 #[test]
754 fn test_parse_empty_object() {
755 let mut parser = ZeroCopyParser::new();
756 let result = parser.parse_lazy(b"{}").unwrap();
757
758 match result {
759 LazyJsonValue::ObjectSlice(bytes) => {
760 assert_eq!(bytes, b"{}");
761 }
762 _ => panic!("Expected object"),
763 }
764 }
765
766 #[test]
767 fn test_parse_empty_array() {
768 let mut parser = ZeroCopyParser::new();
769 let result = parser.parse_lazy(b"[]").unwrap();
770
771 match result {
772 LazyJsonValue::ArraySlice(bytes) => {
773 assert_eq!(bytes, b"[]");
774 }
775 _ => panic!("Expected array"),
776 }
777 }
778
779 #[test]
780 fn test_memory_usage() {
781 let mut parser = ZeroCopyParser::new();
782
783 let result1 = parser.parse_lazy(br#""hello""#).unwrap();
785 let usage1 = result1.memory_usage();
786 assert_eq!(usage1.allocated_bytes, 0);
787 assert_eq!(usage1.referenced_bytes, 5);
788 assert_eq!(usage1.efficiency(), 1.0);
789
790 parser.reset();
792 let result2 = parser.parse_lazy(br#""he\"llo""#).unwrap();
793 let usage2 = result2.memory_usage();
794 assert!(usage2.allocated_bytes > 0);
795 assert_eq!(usage2.referenced_bytes, 0);
796 assert_eq!(usage2.efficiency(), 0.0);
797 }
798
799 #[test]
800 fn test_complex_object() {
801 let mut parser = ZeroCopyParser::new();
802 let input = br#"{"name": "test", "value": 42, "active": true}"#;
803
804 let result = parser.parse_lazy(input).unwrap();
805 match result {
806 LazyJsonValue::ObjectSlice(bytes) => {
807 assert_eq!(bytes.len(), input.len());
808 }
809 _ => panic!("Expected object"),
810 }
811 }
812
813 #[test]
814 fn test_parser_reuse() {
815 let mut parser = ZeroCopyParser::new();
816
817 let result1 = parser.parse_lazy(b"123").unwrap();
819 assert!(matches!(result1, LazyJsonValue::NumberSlice(_)));
820
821 parser.reset();
823 let result2 = parser.parse_lazy(br#""hello""#).unwrap();
824 assert!(matches!(result2, LazyJsonValue::StringBorrowed(_)));
825 }
826
827 #[test]
828 fn test_escape_sequence_slash() {
829 let mut parser = ZeroCopyParser::new();
830 let input = br#""path\/to\/file""#;
831
832 let result = parser.parse_lazy(input).unwrap();
833 match result {
834 LazyJsonValue::StringOwned(s) => {
835 assert_eq!(s, "path/to/file");
836 }
837 _ => panic!("Expected owned string due to escapes"),
838 }
839 }
840
841 #[test]
842 fn test_escape_sequence_backspace() {
843 let mut parser = ZeroCopyParser::new();
844 let input = br#""text\bwith\bbackspace""#;
845
846 let result = parser.parse_lazy(input).unwrap();
847 match result {
848 LazyJsonValue::StringOwned(s) => {
849 assert_eq!(s, "text\x08with\x08backspace");
850 }
851 _ => panic!("Expected owned string due to escapes"),
852 }
853 }
854
855 #[test]
856 fn test_escape_sequence_formfeed() {
857 let mut parser = ZeroCopyParser::new();
858 let input = br#""text\fwith\fformfeed""#;
859
860 let result = parser.parse_lazy(input).unwrap();
861 match result {
862 LazyJsonValue::StringOwned(s) => {
863 assert_eq!(s, "text\x0Cwith\x0Cformfeed");
864 }
865 _ => panic!("Expected owned string due to escapes"),
866 }
867 }
868
869 #[test]
870 fn test_escape_sequence_unicode_basic() {
871 let mut parser = ZeroCopyParser::new();
872 let input = br#""text\u0041""#;
873
874 let result = parser.parse_lazy(input).unwrap();
875 match result {
876 LazyJsonValue::StringOwned(s) => {
877 assert_eq!(s, "textA");
878 }
879 _ => panic!("Expected owned string due to escapes"),
880 }
881 }
882
883 #[test]
884 fn test_escape_sequence_unicode_surrogate_pair() {
885 let mut parser = ZeroCopyParser::new();
886 let input = br#""\uD83D\uDE00""#;
888
889 let result = parser.parse_lazy(input).unwrap();
890 match result {
891 LazyJsonValue::StringOwned(s) => {
892 assert_eq!(s, "\u{1F600}");
893 }
894 _ => panic!("Expected owned string due to escapes"),
895 }
896 }
897
898 #[test]
899 fn test_escape_sequence_unicode_unpaired_high_surrogate_errors() {
900 let mut parser = ZeroCopyParser::new();
901 let input = br#""\uD83D""#;
903
904 let result = parser.parse_lazy(input);
905 assert!(result.is_err());
906 }
907
908 #[test]
909 fn test_escape_sequence_unicode_lone_low_surrogate_errors() {
910 let mut parser = ZeroCopyParser::new();
911 let input = br#""\uDE00""#;
912
913 let result = parser.parse_lazy(input);
914 assert!(result.is_err());
915 }
916
917 #[test]
918 fn test_escape_sequence_unicode_hex_too_short_errors() {
919 let mut parser = ZeroCopyParser::new();
920 let input = br#""\u00""#;
921
922 let result = parser.parse_lazy(input);
923 assert!(result.is_err());
924 }
925
926 #[test]
927 fn test_escape_sequence_unicode_invalid_hex_digit_errors() {
928 let mut parser = ZeroCopyParser::new();
929 let input = br#""\uZZZZ""#;
930
931 let result = parser.parse_lazy(input);
932 assert!(result.is_err());
933 }
934
935 #[test]
936 fn test_escape_sequence_unicode_leading_plus_rejected() {
937 let mut parser = ZeroCopyParser::new();
938 let input = br#""\u+041""#;
941
942 let result = parser.parse_lazy(input);
943 assert!(result.is_err());
944 }
945
946 #[test]
947 fn test_escape_sequence_unicode_high_surrogate_not_followed_by_escape_errors() {
948 let mut parser = ZeroCopyParser::new();
949 let input = br#""\uD83DAB""#;
951
952 let result = parser.parse_lazy(input);
953 assert!(result.is_err());
954 }
955
956 #[test]
957 fn test_escape_sequence_unicode_high_surrogate_followed_by_non_u_escape_errors() {
958 let mut parser = ZeroCopyParser::new();
959 let input = br#""\uD83D\n""#;
961
962 let result = parser.parse_lazy(input);
963 assert!(result.is_err());
964 }
965
966 #[test]
967 fn test_escape_sequence_unicode_high_surrogate_followed_by_non_low_surrogate_errors() {
968 let mut parser = ZeroCopyParser::new();
969 let input = br#""\uD83D\u0041""#;
971
972 let result = parser.parse_lazy(input);
973 assert!(result.is_err());
974 }
975
976 #[test]
977 fn test_escape_sequence_unicode_null_codepoint() {
978 let mut parser = ZeroCopyParser::new();
979 let input = br#""\u0000""#;
980
981 let result = parser.parse_lazy(input).unwrap();
982 match result {
983 LazyJsonValue::StringOwned(s) => {
984 assert_eq!(s, "\u{0000}");
985 }
986 _ => panic!("Expected owned string due to escapes"),
987 }
988 }
989
990 #[test]
991 fn test_escape_sequence_unicode_two_byte_char() {
992 let mut parser = ZeroCopyParser::new();
993 let input = br#""\u00e9""#;
995
996 let result = parser.parse_lazy(input).unwrap();
997 match result {
998 LazyJsonValue::StringOwned(s) => {
999 assert_eq!(s, "\u{00e9}");
1000 }
1001 _ => panic!("Expected owned string due to escapes"),
1002 }
1003 }
1004
1005 #[test]
1006 fn test_escape_sequence_unicode_three_byte_char() {
1007 let mut parser = ZeroCopyParser::new();
1008 let input = br#""\u4e2d""#;
1010
1011 let result = parser.parse_lazy(input).unwrap();
1012 match result {
1013 LazyJsonValue::StringOwned(s) => {
1014 assert_eq!(s, "\u{4e2d}");
1015 }
1016 _ => panic!("Expected owned string due to escapes"),
1017 }
1018 }
1019
1020 #[test]
1021 fn test_escape_sequence_unicode_max_bmp_noncharacter() {
1022 let mut parser = ZeroCopyParser::new();
1023 let input = br#""\uffff""#;
1024
1025 let result = parser.parse_lazy(input).unwrap();
1026 match result {
1027 LazyJsonValue::StringOwned(s) => {
1028 assert_eq!(s, "\u{ffff}");
1029 }
1030 _ => panic!("Expected owned string due to escapes"),
1031 }
1032 }
1033
1034 #[test]
1035 fn test_escape_sequence_unicode_lowercase_hex_surrogate_pair() {
1036 let mut parser = ZeroCopyParser::new();
1037 let input = br#""\ud83d\ude00""#;
1038
1039 let result = parser.parse_lazy(input).unwrap();
1040 match result {
1041 LazyJsonValue::StringOwned(s) => {
1042 assert_eq!(s, "\u{1F600}");
1043 }
1044 _ => panic!("Expected owned string due to escapes"),
1045 }
1046 }
1047
1048 #[test]
1049 fn test_escape_sequence_unicode_surrogate_pair_with_surrounding_ascii() {
1050 let mut parser = ZeroCopyParser::new();
1051 let input = br#""a\uD83D\uDE00b""#;
1052
1053 let result = parser.parse_lazy(input).unwrap();
1054 match result {
1055 LazyJsonValue::StringOwned(s) => {
1056 assert_eq!(s, "a\u{1F600}b");
1057 }
1058 _ => panic!("Expected owned string due to escapes"),
1059 }
1060 }
1061
1062 #[test]
1063 fn test_number_parsing_partial() {
1064 let mut parser = ZeroCopyParser::new();
1065 let result = parser.parse_lazy(b"123");
1067 assert!(result.is_ok());
1068 assert!(matches!(result.unwrap(), LazyJsonValue::NumberSlice(_)));
1069 }
1070
1071 #[test]
1072 fn test_number_parsing_error_overflow() {
1073 let mut parser = ZeroCopyParser::new();
1074 let input = b"99999999999999999999999999999999999999999999999999";
1076 let result = parser.parse_lazy(input);
1077 assert!(result.is_ok() || result.is_err());
1079 }
1080
1081 #[test]
1082 fn test_incremental_parser_feed() {
1083 let mut parser = IncrementalParser::new();
1084
1085 let result = parser.feed(b"{\"key\":");
1087 assert!(result.is_ok());
1088
1089 let result2 = parser.feed(b"\"value\"}");
1091 assert!(result2.is_ok());
1092 }
1093
1094 #[test]
1095 fn test_incremental_parser_multiple_feeds() {
1096 let mut parser = IncrementalParser::new();
1097
1098 parser.feed(b"[1,").unwrap();
1099 parser.feed(b"2,").unwrap();
1100 parser.feed(b"3]").unwrap();
1101 }
1102
1103 #[test]
1104 fn test_lazy_json_value_matches() {
1105 let num = LazyJsonValue::NumberSlice(b"123");
1106 assert!(matches!(num, LazyJsonValue::NumberSlice(_)));
1107 assert!(!num.is_null());
1108
1109 let null = LazyJsonValue::Null;
1110 assert!(null.is_null());
1111 assert!(!matches!(null, LazyJsonValue::NumberSlice(_)));
1112
1113 let bool_val = LazyJsonValue::Boolean(true);
1114 assert!(matches!(bool_val, LazyJsonValue::Boolean(true)));
1115 assert!(!bool_val.is_null());
1116 }
1117
1118 #[test]
1119 fn test_memory_usage_zero_copy_efficiency() {
1120 let borrowed = LazyJsonValue::StringBorrowed(b"test");
1121 let usage = borrowed.memory_usage();
1122 assert_eq!(usage.efficiency(), 1.0);
1123 assert_eq!(usage.allocated_bytes, 0);
1124
1125 let owned = LazyJsonValue::StringOwned("test".to_string());
1126 let usage2 = owned.memory_usage();
1127 assert_eq!(usage2.efficiency(), 0.0);
1128 assert!(usage2.allocated_bytes > 0);
1129 }
1130}