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 if i + 5 < input.len() {
362 i += 6;
364 continue;
365 } else {
366 return Err(DomainError::InvalidInput(
367 "Invalid unicode escape".to_string(),
368 ));
369 }
370 }
371 _ => {
372 return Err(DomainError::InvalidInput(
373 "Invalid escape sequence".to_string(),
374 ));
375 }
376 }
377 i += 2;
378 } else {
379 result.push(input[i]);
380 i += 1;
381 }
382 }
383
384 String::from_utf8(result)
385 .map_err(|e| DomainError::InvalidInput(format!("Invalid UTF-8: {e}")))
386 }
387}
388
389impl<'a> LazyParser<'a> for ZeroCopyParser<'a> {
390 type Output = LazyJsonValue<'a>;
391 type Error = DomainError;
392
393 fn parse_lazy(&mut self, input: &'a [u8]) -> Result<Self::Output, Self::Error> {
394 self.validator
396 .validate_input_size(input.len())
397 .map_err(|e| DomainError::SecurityViolation(e.to_string()))?;
398
399 self.input = input;
400 self.position = 0;
401 self.depth = 0;
402
403 self.parse_value()
404 }
405
406 fn remaining(&self) -> &'a [u8] {
407 if self.position < self.input.len() {
408 &self.input[self.position..]
409 } else {
410 &[]
411 }
412 }
413
414 fn is_complete(&self) -> bool {
415 self.position >= self.input.len()
416 }
417
418 fn reset(&mut self) {
419 self.input = &[];
420 self.position = 0;
421 self.depth = 0;
422 }
423}
424
425#[derive(Debug, Clone, PartialEq)]
427pub enum LazyJsonValue<'a> {
428 StringBorrowed(&'a [u8]),
430 StringOwned(String),
432 NumberSlice(&'a [u8]),
434 Boolean(bool),
436 Null,
438 ObjectSlice(&'a [u8]),
440 ArraySlice(&'a [u8]),
442}
443
444impl<'a> LazyJsonValue<'a> {
445 pub fn value_type(&self) -> ValueType {
447 match self {
448 LazyJsonValue::StringBorrowed(_) | LazyJsonValue::StringOwned(_) => ValueType::String,
449 LazyJsonValue::NumberSlice(_) => ValueType::Number,
450 LazyJsonValue::Boolean(_) => ValueType::Boolean,
451 LazyJsonValue::Null => ValueType::Null,
452 LazyJsonValue::ObjectSlice(_) => ValueType::Object,
453 LazyJsonValue::ArraySlice(_) => ValueType::Array,
454 }
455 }
456
457 pub fn to_string_lossy(&self) -> String {
459 match self {
460 LazyJsonValue::StringBorrowed(bytes) => String::from_utf8_lossy(bytes).to_string(),
461 LazyJsonValue::StringOwned(s) => s.clone(),
462 LazyJsonValue::NumberSlice(bytes) => String::from_utf8_lossy(bytes).to_string(),
463 LazyJsonValue::Boolean(b) => b.to_string(),
464 LazyJsonValue::Null => "null".to_string(),
465 LazyJsonValue::ObjectSlice(bytes) => String::from_utf8_lossy(bytes).to_string(),
466 LazyJsonValue::ArraySlice(bytes) => String::from_utf8_lossy(bytes).to_string(),
467 }
468 }
469
470 pub fn as_str(&self) -> DomainResult<&str> {
472 match self {
473 LazyJsonValue::StringBorrowed(bytes) => from_utf8(bytes)
474 .map_err(|e| DomainError::InvalidInput(format!("Invalid UTF-8: {e}"))),
475 LazyJsonValue::StringOwned(s) => Ok(s.as_str()),
476 _ => Err(DomainError::InvalidInput(
477 "Value is not a string".to_string(),
478 )),
479 }
480 }
481
482 pub fn as_number(&self) -> DomainResult<f64> {
484 match self {
485 LazyJsonValue::NumberSlice(bytes) => {
486 let s = from_utf8(bytes)
487 .map_err(|e| DomainError::InvalidInput(format!("Invalid UTF-8: {e}")))?;
488 s.parse::<f64>()
489 .map_err(|e| DomainError::InvalidInput(format!("Invalid number: {e}")))
490 }
491 _ => Err(DomainError::InvalidInput(
492 "Value is not a number".to_string(),
493 )),
494 }
495 }
496
497 pub fn as_boolean(&self) -> DomainResult<bool> {
499 match self {
500 LazyJsonValue::Boolean(b) => Ok(*b),
501 _ => Err(DomainError::InvalidInput(
502 "Value is not a boolean".to_string(),
503 )),
504 }
505 }
506
507 pub fn is_null(&self) -> bool {
509 matches!(self, LazyJsonValue::Null)
510 }
511
512 pub fn as_bytes(&self) -> Option<&'a [u8]> {
514 match self {
515 LazyJsonValue::StringBorrowed(bytes) => Some(bytes),
516 LazyJsonValue::NumberSlice(bytes) => Some(bytes),
517 LazyJsonValue::ObjectSlice(bytes) => Some(bytes),
518 LazyJsonValue::ArraySlice(bytes) => Some(bytes),
519 _ => None,
520 }
521 }
522
523 pub fn memory_usage(&self) -> MemoryUsage {
525 match self {
526 LazyJsonValue::StringBorrowed(bytes) => MemoryUsage {
527 allocated_bytes: 0,
528 referenced_bytes: bytes.len(),
529 },
530 LazyJsonValue::StringOwned(s) => MemoryUsage {
531 allocated_bytes: s.len(),
532 referenced_bytes: 0,
533 },
534 LazyJsonValue::NumberSlice(bytes) => MemoryUsage {
535 allocated_bytes: 0,
536 referenced_bytes: bytes.len(),
537 },
538 LazyJsonValue::Boolean(val) => MemoryUsage {
539 allocated_bytes: 0,
540 referenced_bytes: if *val { 4 } else { 5 }, },
542 LazyJsonValue::Null => MemoryUsage {
543 allocated_bytes: 0,
544 referenced_bytes: 4, },
546 LazyJsonValue::ObjectSlice(bytes) => MemoryUsage {
547 allocated_bytes: 0,
548 referenced_bytes: bytes.len(),
549 },
550 LazyJsonValue::ArraySlice(bytes) => MemoryUsage {
551 allocated_bytes: 0,
552 referenced_bytes: bytes.len(),
553 },
554 }
555 }
556}
557
558#[derive(Debug, Clone, PartialEq)]
560pub struct MemoryUsage {
561 pub allocated_bytes: usize,
563 pub referenced_bytes: usize,
565}
566
567impl MemoryUsage {
568 pub fn total(&self) -> usize {
570 self.allocated_bytes + self.referenced_bytes
571 }
572
573 pub fn efficiency(&self) -> f64 {
575 if self.total() == 0 {
576 1.0
577 } else {
578 self.referenced_bytes as f64 / self.total() as f64
579 }
580 }
581}
582
583pub struct IncrementalParser<'a> {
585 buffer: Vec<u8>,
586 _phantom: std::marker::PhantomData<&'a ()>,
587}
588
589impl<'a> Default for IncrementalParser<'a> {
590 fn default() -> Self {
591 Self::new()
592 }
593}
594
595impl<'a> IncrementalParser<'a> {
596 pub fn new() -> Self {
598 Self {
599 buffer: Vec::with_capacity(8192), _phantom: std::marker::PhantomData,
601 }
602 }
603
604 pub fn feed(&mut self, data: &[u8]) -> DomainResult<()> {
606 self.buffer.extend_from_slice(data);
607 Ok(())
608 }
609
610 pub fn parse_available(&mut self) -> DomainResult<Vec<LazyJsonValue<'_>>> {
612 if !self.buffer.is_empty() {
615 let mut parser = ZeroCopyParser::new();
616 match parser.parse_lazy(&self.buffer) {
617 Ok(_value) => {
618 self.buffer.clear();
621 Ok(vec![])
622 }
623 Err(_e) => Ok(vec![]), }
625 } else {
626 Ok(vec![])
627 }
628 }
629
630 pub fn has_complete_value(&self) -> bool {
632 !self.buffer.is_empty()
634 }
635}
636
637impl<'a> Default for ZeroCopyParser<'a> {
638 fn default() -> Self {
639 Self::new()
640 }
641}
642
643#[cfg(test)]
644mod tests {
645 use super::*;
646
647 #[test]
648 fn test_parse_string() {
649 let mut parser = ZeroCopyParser::new();
650 let input = br#""hello world""#;
651
652 let result = parser.parse_lazy(input).unwrap();
653 match result {
654 LazyJsonValue::StringBorrowed(bytes) => {
655 assert_eq!(bytes, b"hello world");
656 }
657 _ => panic!("Expected string"),
658 }
659 }
660
661 #[test]
662 fn test_parse_escaped_string() {
663 let mut parser = ZeroCopyParser::new();
664 let input = br#""hello \"world\"""#;
665
666 let result = parser.parse_lazy(input).unwrap();
667 match result {
668 LazyJsonValue::StringOwned(s) => {
669 assert_eq!(s, "hello \"world\"");
670 }
671 _ => panic!("Expected owned string due to escapes"),
672 }
673 }
674
675 #[test]
676 fn test_parse_number() {
677 let mut parser = ZeroCopyParser::new();
678 let input = b"123.45";
679
680 let result = parser.parse_lazy(input).unwrap();
681 match result {
682 LazyJsonValue::NumberSlice(bytes) => {
683 assert_eq!(bytes, b"123.45");
684 assert_eq!(result.as_number().unwrap(), 123.45);
685 }
686 _ => panic!("Expected number"),
687 }
688 }
689
690 #[test]
691 fn test_parse_boolean() {
692 let mut parser = ZeroCopyParser::new();
693
694 let result = parser.parse_lazy(b"true").unwrap();
695 assert_eq!(result, LazyJsonValue::Boolean(true));
696
697 parser.reset();
698 let result = parser.parse_lazy(b"false").unwrap();
699 assert_eq!(result, LazyJsonValue::Boolean(false));
700 }
701
702 #[test]
703 fn test_parse_null() {
704 let mut parser = ZeroCopyParser::new();
705 let result = parser.parse_lazy(b"null").unwrap();
706 assert_eq!(result, LazyJsonValue::Null);
707 assert!(result.is_null());
708 }
709
710 #[test]
711 fn test_parse_empty_object() {
712 let mut parser = ZeroCopyParser::new();
713 let result = parser.parse_lazy(b"{}").unwrap();
714
715 match result {
716 LazyJsonValue::ObjectSlice(bytes) => {
717 assert_eq!(bytes, b"{}");
718 }
719 _ => panic!("Expected object"),
720 }
721 }
722
723 #[test]
724 fn test_parse_empty_array() {
725 let mut parser = ZeroCopyParser::new();
726 let result = parser.parse_lazy(b"[]").unwrap();
727
728 match result {
729 LazyJsonValue::ArraySlice(bytes) => {
730 assert_eq!(bytes, b"[]");
731 }
732 _ => panic!("Expected array"),
733 }
734 }
735
736 #[test]
737 fn test_memory_usage() {
738 let mut parser = ZeroCopyParser::new();
739
740 let result1 = parser.parse_lazy(br#""hello""#).unwrap();
742 let usage1 = result1.memory_usage();
743 assert_eq!(usage1.allocated_bytes, 0);
744 assert_eq!(usage1.referenced_bytes, 5);
745 assert_eq!(usage1.efficiency(), 1.0);
746
747 parser.reset();
749 let result2 = parser.parse_lazy(br#""he\"llo""#).unwrap();
750 let usage2 = result2.memory_usage();
751 assert!(usage2.allocated_bytes > 0);
752 assert_eq!(usage2.referenced_bytes, 0);
753 assert_eq!(usage2.efficiency(), 0.0);
754 }
755
756 #[test]
757 fn test_complex_object() {
758 let mut parser = ZeroCopyParser::new();
759 let input = br#"{"name": "test", "value": 42, "active": true}"#;
760
761 let result = parser.parse_lazy(input).unwrap();
762 match result {
763 LazyJsonValue::ObjectSlice(bytes) => {
764 assert_eq!(bytes.len(), input.len());
765 }
766 _ => panic!("Expected object"),
767 }
768 }
769
770 #[test]
771 fn test_parser_reuse() {
772 let mut parser = ZeroCopyParser::new();
773
774 let result1 = parser.parse_lazy(b"123").unwrap();
776 assert!(matches!(result1, LazyJsonValue::NumberSlice(_)));
777
778 parser.reset();
780 let result2 = parser.parse_lazy(br#""hello""#).unwrap();
781 assert!(matches!(result2, LazyJsonValue::StringBorrowed(_)));
782 }
783
784 #[test]
785 fn test_escape_sequence_slash() {
786 let mut parser = ZeroCopyParser::new();
787 let input = br#""path\/to\/file""#;
788
789 let result = parser.parse_lazy(input).unwrap();
790 match result {
791 LazyJsonValue::StringOwned(s) => {
792 assert_eq!(s, "path/to/file");
793 }
794 _ => panic!("Expected owned string due to escapes"),
795 }
796 }
797
798 #[test]
799 fn test_escape_sequence_backspace() {
800 let mut parser = ZeroCopyParser::new();
801 let input = br#""text\bwith\bbackspace""#;
802
803 let result = parser.parse_lazy(input).unwrap();
804 match result {
805 LazyJsonValue::StringOwned(s) => {
806 assert_eq!(s, "text\x08with\x08backspace");
807 }
808 _ => panic!("Expected owned string due to escapes"),
809 }
810 }
811
812 #[test]
813 fn test_escape_sequence_formfeed() {
814 let mut parser = ZeroCopyParser::new();
815 let input = br#""text\fwith\fformfeed""#;
816
817 let result = parser.parse_lazy(input).unwrap();
818 match result {
819 LazyJsonValue::StringOwned(s) => {
820 assert_eq!(s, "text\x0Cwith\x0Cformfeed");
821 }
822 _ => panic!("Expected owned string due to escapes"),
823 }
824 }
825
826 #[test]
827 fn test_escape_sequence_unicode_basic() {
828 let mut parser = ZeroCopyParser::new();
829 let input = br#""text\u0041""#;
831
832 let result = parser.parse_lazy(input);
833 assert!(result.is_ok());
835 }
836
837 #[test]
838 fn test_number_parsing_partial() {
839 let mut parser = ZeroCopyParser::new();
840 let result = parser.parse_lazy(b"123");
842 assert!(result.is_ok());
843 assert!(matches!(result.unwrap(), LazyJsonValue::NumberSlice(_)));
844 }
845
846 #[test]
847 fn test_number_parsing_error_overflow() {
848 let mut parser = ZeroCopyParser::new();
849 let input = b"99999999999999999999999999999999999999999999999999";
851 let result = parser.parse_lazy(input);
852 assert!(result.is_ok() || result.is_err());
854 }
855
856 #[test]
857 fn test_incremental_parser_feed() {
858 let mut parser = IncrementalParser::new();
859
860 let result = parser.feed(b"{\"key\":");
862 assert!(result.is_ok());
863
864 let result2 = parser.feed(b"\"value\"}");
866 assert!(result2.is_ok());
867 }
868
869 #[test]
870 fn test_incremental_parser_multiple_feeds() {
871 let mut parser = IncrementalParser::new();
872
873 parser.feed(b"[1,").unwrap();
874 parser.feed(b"2,").unwrap();
875 parser.feed(b"3]").unwrap();
876 }
877
878 #[test]
879 fn test_lazy_json_value_matches() {
880 let num = LazyJsonValue::NumberSlice(b"123");
881 assert!(matches!(num, LazyJsonValue::NumberSlice(_)));
882 assert!(!num.is_null());
883
884 let null = LazyJsonValue::Null;
885 assert!(null.is_null());
886 assert!(!matches!(null, LazyJsonValue::NumberSlice(_)));
887
888 let bool_val = LazyJsonValue::Boolean(true);
889 assert!(matches!(bool_val, LazyJsonValue::Boolean(true)));
890 assert!(!bool_val.is_null());
891 }
892
893 #[test]
894 fn test_memory_usage_zero_copy_efficiency() {
895 let borrowed = LazyJsonValue::StringBorrowed(b"test");
896 let usage = borrowed.memory_usage();
897 assert_eq!(usage.efficiency(), 1.0);
898 assert_eq!(usage.allocated_bytes, 0);
899
900 let owned = LazyJsonValue::StringOwned("test".to_string());
901 let usage2 = owned.memory_usage();
902 assert_eq!(usage2.efficiency(), 0.0);
903 assert!(usage2.allocated_bytes > 0);
904 }
905}