• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kaidokert / picojson-rs / 16708793874

03 Aug 2025 07:48PM UTC coverage: 93.313% (-0.7%) from 94.008%
16708793874

Pull #77

github

web-flow
Merge 6f7b76718 into 377ce19f7
Pull Request #77: Datasource intro

483 of 578 new or added lines in 9 files covered. (83.56%)

63 existing lines in 6 files now uncovered.

4996 of 5354 relevant lines covered (93.31%)

1311.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.77
/picojson/src/stream_parser.rs
1
// SPDX-License-Identifier: Apache-2.0
2

3
use crate::event_processor::{EscapeTiming, ParserCore};
4
use crate::parse_error::ParseError;
5
use crate::shared::Event;
6
use crate::stream_content_builder::StreamContentBuilder;
7
#[cfg(test)]
8
use crate::NumberResult;
9
use crate::{ujson, PullParser};
10

11
use ujson::{BitStackConfig, DefaultConfig};
12

13
/// Trait for input sources that can provide data to the streaming parser.
14
pub trait Reader {
15
    /// The error type returned by read operations
16
    type Error;
17

18
    /// Read data into the provided buffer.
19
    /// Returns the number of bytes read, or an error.
20
    ///
21
    /// # Contract
22
    /// - A return value of 0 **MUST** indicate true end of stream
23
    /// - Implementations **MUST NOT** return 0 unless no more data will ever be available
24
    /// - Returning 0 followed by non-zero reads in subsequent calls violates this contract
25
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
26
}
27

28
/// A pull parser that parses JSON from a stream.
29
///
30
/// Generic over BitStackConfig for configurable nesting depth.
31
/// It is designed to be used with the [Reader] trait, which is used to read data from a stream.
32
///
33
pub struct StreamParser<'b, R: Reader, C: BitStackConfig = DefaultConfig> {
34
    /// The shared parser core that handles the unified event processing loop
35
    parser_core: ParserCore<C::Bucket, C::Counter>,
36
    /// The content builder that handles StreamParser-specific content extraction and reader access
37
    content_builder: StreamContentBuilder<'b, R>,
38
}
39

40
/// Methods for StreamParser using DefaultConfig
41
impl<'b, R: Reader> StreamParser<'b, R, DefaultConfig> {
42
    /// Create a new StreamParser with default configuration
43
    ///
44
    /// Uses the default BitStack configuration (u32 bucket, u8 counter)
45
    /// for most common use cases.
46
    pub fn new(reader: R, buffer: &'b mut [u8]) -> Self {
1,036✔
47
        Self::with_config(reader, buffer)
1,036✔
48
    }
1,036✔
49
}
50

51
/// Methods for StreamParser with custom BitStackConfig
52
impl<'b, R: Reader, C: BitStackConfig> StreamParser<'b, R, C> {
53
    /// Create a new StreamParser with custom configuration
54
    ///
55
    /// Use this when you need custom BitStack storage types for specific
56
    /// memory or nesting depth requirements.
57
    ///
58
    /// # Example
59
    /// ```
60
    /// use picojson::{StreamParser, BitStackStruct, ChunkReader};
61
    ///
62
    /// let json = b"{\"test\": 42}";
63
    /// // For testing, ChunkReader is a convenient Reader implementation
64
    /// let reader = ChunkReader::new(json, 10);
65
    /// let mut buffer = [0u8; 256];
66
    ///
67
    /// // Custom configuration: u64 bucket + u16 counter for deeper nesting
68
    /// let mut parser = StreamParser::<_, BitStackStruct<u64, u16>>::with_config(reader, &mut buffer);
69
    /// ```
70
    pub fn with_config(reader: R, buffer: &'b mut [u8]) -> Self {
1,078✔
71
        Self {
1,078✔
72
            parser_core: ParserCore::new(),
1,078✔
73
            content_builder: StreamContentBuilder::new(buffer, reader),
1,078✔
74
        }
1,078✔
75
    }
1,078✔
76
}
77

78
/// Shared methods for StreamParser with any BitStackConfig
79
impl<R: Reader, C: BitStackConfig> StreamParser<'_, R, C> {
80
    /// Get the next JSON event from the stream
81
    fn next_event_impl(&mut self) -> Result<Event<'_, '_>, ParseError> {
4,954✔
82
        // Use the unified ParserCore implementation with StreamParser-specific timing
83
        // StreamParser needs byte accumulation for string parsing
84
        self.parser_core.next_event_impl(
4,954✔
85
            &mut self.content_builder,
4,954✔
86
            EscapeTiming::OnEnd,
4,954✔
87
            |provider, byte| {
10,770✔
88
                // Delegate to the StreamContentBuilder's byte accumulation logic
89
                provider.handle_byte_accumulation(byte)
10,770✔
90
            },
10,770✔
91
        )
92
    }
4,954✔
93
}
94

95
impl<R: Reader, C: BitStackConfig> PullParser for StreamParser<'_, R, C> {
96
    fn next_event(&mut self) -> Result<Event<'_, '_>, ParseError> {
4,958✔
97
        // Check if we're already finished (similar to SliceParser's is_past_end check)
98
        if self.content_builder.is_finished() {
4,958✔
99
            return Ok(Event::EndDocument);
4✔
100
        }
4,954✔
101

102
        self.content_builder.apply_unescaped_reset_if_queued();
4,954✔
103

104
        self.next_event_impl()
4,954✔
105
    }
4,958✔
106
}
107

108
#[cfg(test)]
109
mod tests {
110
    use super::*;
111

112
    /// Simple test reader that reads from a byte slice
113
    pub struct SliceReader<'a> {
114
        data: &'a [u8],
115
        position: usize,
116
    }
117

118
    impl<'a> SliceReader<'a> {
119
        pub fn new(data: &'a [u8]) -> Self {
39✔
120
            Self { data, position: 0 }
39✔
121
        }
39✔
122
    }
123

124
    impl Reader for SliceReader<'_> {
125
        type Error = ();
126

127
        fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
65✔
128
            let remaining = self.data.len().saturating_sub(self.position);
65✔
129
            if remaining == 0 {
65✔
130
                return Ok(0); // EOF
26✔
131
            }
39✔
132

133
            let to_copy = remaining.min(buf.len());
39✔
134
            let end_pos = self.position.saturating_add(to_copy);
39✔
135
            if let (Some(dest), Some(src)) = (
39✔
136
                buf.get_mut(..to_copy),
39✔
137
                self.data.get(self.position..end_pos),
39✔
138
            ) {
139
                dest.copy_from_slice(src);
39✔
140
                self.position = end_pos;
39✔
141
                Ok(to_copy)
39✔
142
            } else {
143
                Err(())
×
144
            }
145
        }
65✔
146
    }
147

148
    type TestStreamParser<'b> = StreamParser<'b, SliceReader<'static>>;
149

150
    #[test]
151
    fn test_direct_parser_simple_object() {
1✔
152
        let json = b"{}";
1✔
153
        let reader = SliceReader::new(json);
1✔
154
        let mut buffer = [0u8; 256];
1✔
155
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
156

157
        // Should get ObjectStart
158
        let event = parser.next_event().unwrap();
1✔
159
        assert!(matches!(event, Event::StartObject));
1✔
160

161
        // Should get ObjectEnd
162
        let event = parser.next_event().unwrap();
1✔
163
        assert!(matches!(event, Event::EndObject));
1✔
164

165
        // Should get EndDocument
166
        let event = parser.next_event().unwrap();
1✔
167
        assert!(matches!(event, Event::EndDocument));
1✔
168
    }
1✔
169

170
    #[test]
171
    fn test_direct_parser_simple_array() {
1✔
172
        let json = b"[]";
1✔
173
        let reader = SliceReader::new(json);
1✔
174
        let mut buffer = [0u8; 256];
1✔
175
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
176

177
        // Should get ArrayStart
178
        let event = parser.next_event().unwrap();
1✔
179
        assert!(matches!(event, Event::StartArray));
1✔
180

181
        // Should get ArrayEnd
182
        let event = parser.next_event().unwrap();
1✔
183
        assert!(matches!(event, Event::EndArray));
1✔
184

185
        // Should get EndDocument
186
        let event = parser.next_event().unwrap();
1✔
187
        assert!(matches!(event, Event::EndDocument));
1✔
188
    }
1✔
189

190
    #[test]
191
    fn test_direct_parser_simple_escape() {
1✔
192
        let json = b"\"hello\\nworld\"";
1✔
193
        let reader = SliceReader::new(json);
1✔
194
        let mut buffer = [0u8; 256];
1✔
195
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
196

197
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
198
            assert_eq!(json_string.as_str(), "hello\nworld");
1✔
199
        } else {
200
            panic!("Expected String event");
×
201
        }
202
    }
1✔
203

204
    #[test]
205
    fn test_pending_state_edge_cases() {
1✔
206
        // Test 1: Complex nested container endings
207
        let json1 = br#"{"a": {"b": [{"c": 123}]}}"#;
1✔
208
        let reader1 = SliceReader::new(json1);
1✔
209
        let mut buffer1 = [0u8; 256];
1✔
210
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
211

212
        let mut events = Vec::new();
1✔
213
        loop {
214
            match parser1.next_event() {
13✔
215
                Ok(Event::EndDocument) => break,
1✔
216
                Ok(event) => events.push(format!("{:?}", event)),
12✔
217
                Err(e) => panic!("Nested containers failed: {:?}", e),
×
218
            }
219
        }
220

221
        // Should contain all expected events
222
        assert!(events.len() >= 8); // StartObject, Key, StartObject, Key, StartArray, StartObject, Key, Number, EndObject, EndArray, EndObject, EndObject
1✔
223

224
        // Test 2: Mixed types after numbers in array
225
        let json2 = br#"[123, "string", true, null, 456]"#;
1✔
226
        let reader2 = SliceReader::new(json2);
1✔
227
        let mut buffer2 = [0u8; 256];
1✔
228
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
229

230
        let mut number_count = 0;
1✔
231
        loop {
232
            match parser2.next_event() {
8✔
233
                Ok(Event::EndDocument) => break,
1✔
234
                Ok(Event::Number(_)) => number_count += 1,
2✔
235
                Ok(_) => {}
5✔
236
                Err(e) => panic!("Mixed types failed: {:?}", e),
×
237
            }
238
        }
239
        assert_eq!(number_count, 2); // Should find both 123 and 456
1✔
240

241
        // Test 3: Empty containers
242
        let json3 = br#"[[], {}, [{}], {"empty": []}]"#;
1✔
243
        let reader3 = SliceReader::new(json3);
1✔
244
        let mut buffer3 = [0u8; 256];
1✔
245
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
246

247
        loop {
248
            match parser3.next_event() {
16✔
249
                Ok(Event::EndDocument) => break,
1✔
250
                Ok(_) => {}
15✔
251
                Err(e) => panic!("Empty containers failed: {:?}", e),
×
252
            }
253
        }
254

255
        // Test 4: Multiple consecutive numbers
256
        let json4 = br#"[1, 2, 3, 4, 5]"#;
1✔
257
        let reader4 = SliceReader::new(json4);
1✔
258
        let mut buffer4 = [0u8; 256];
1✔
259
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
1✔
260

261
        let mut consecutive_numbers = Vec::new();
1✔
262
        loop {
263
            match parser4.next_event() {
8✔
264
                Ok(Event::EndDocument) => break,
1✔
265
                Ok(Event::Number(n)) => consecutive_numbers.push(n.as_str().to_string()),
5✔
266
                Ok(_) => {}
2✔
267
                Err(e) => panic!("Consecutive numbers failed: {:?}", e),
×
268
            }
269
        }
270
        assert_eq!(consecutive_numbers, vec!["1", "2", "3", "4", "5"]);
1✔
271
    }
1✔
272

273
    #[test]
274
    fn test_error_recovery_with_pending_state() {
1✔
275
        // Test error handling - this should fail gracefully without hanging onto pending state
276
        let invalid_json = br#"{"key": 123,"#; // Missing closing brace
1✔
277
        let reader = SliceReader::new(invalid_json);
1✔
278
        let mut buffer = [0u8; 256];
1✔
279
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
280

281
        // Parse until we hit an error or EOF
282
        loop {
283
            match parser.next_event() {
4✔
284
                Ok(Event::EndDocument) => break, // EOF reached
×
285
                Ok(_) => {}
3✔
286
                Err(_) => break, // Error occurred - this is expected
1✔
287
            }
288
        }
289

290
        // The important thing is that we don't panic or hang
291
        // The specific error behavior may vary
292
    }
1✔
293

294
    #[test]
295
    fn test_multiple_rapid_container_ends() {
1✔
296
        // Test deeply nested structures that end with numbers
297
        // This tests whether we can handle multiple rapid container ends correctly
298

299
        // Test 1: Deeply nested arrays ending with number
300
        let json1 = br#"[[[123]]]"#;
1✔
301
        let reader1 = SliceReader::new(json1);
1✔
302
        let mut buffer1 = [0u8; 256];
1✔
303
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
304

305
        let mut events1 = Vec::new();
1✔
306
        loop {
307
            match parser1.next_event() {
8✔
308
                Ok(Event::EndDocument) => break,
1✔
309
                Ok(event) => events1.push(format!("{:?}", event)),
7✔
310
                Err(e) => panic!("Deeply nested arrays failed: {:?}", e),
×
311
            }
312
        }
313

314
        // Should have: StartArray, StartArray, StartArray, Number(123), EndArray, EndArray, EndArray
315
        assert_eq!(events1.len(), 7);
1✔
316
        assert!(events1[3].contains("Number"));
1✔
317
        assert_eq!(&events1[4], "EndArray");
1✔
318
        assert_eq!(&events1[5], "EndArray");
1✔
319
        assert_eq!(&events1[6], "EndArray");
1✔
320

321
        // Test 2: Mixed nested containers ending with number
322
        let json2 = br#"{"a": [{"b": 456}]}"#;
1✔
323
        let reader2 = SliceReader::new(json2);
1✔
324
        let mut buffer2 = [0u8; 256];
1✔
325
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
326

327
        let mut events2 = Vec::new();
1✔
328
        loop {
329
            match parser2.next_event() {
10✔
330
                Ok(Event::EndDocument) => break,
1✔
331
                Ok(event) => events2.push(format!("{:?}", event)),
9✔
332
                Err(e) => panic!("Mixed nested containers failed: {:?}", e),
×
333
            }
334
        }
335

336
        // Should properly handle the sequence of: number -> EndObject -> EndArray -> EndObject
337
        assert!(events2.len() >= 8);
1✔
338

339
        // Test 3: Multiple numbers at different nesting levels
340
        let json3 = br#"[123, [456, [789]]]"#;
1✔
341
        let reader3 = SliceReader::new(json3);
1✔
342
        let mut buffer3 = [0u8; 256];
1✔
343
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
344

345
        let mut number_count = 0;
1✔
346
        let mut events3 = Vec::new();
1✔
347
        loop {
348
            match parser3.next_event() {
10✔
349
                Ok(Event::EndDocument) => break,
1✔
350
                Ok(Event::Number(n)) => {
3✔
351
                    number_count += 1;
3✔
352
                    events3.push(format!("Number({})", n.as_str()));
3✔
353
                }
3✔
354
                Ok(event) => events3.push(format!("{:?}", event)),
6✔
355
                Err(e) => panic!("Multiple nested numbers failed: {:?}", e),
×
356
            }
357
        }
358

359
        assert_eq!(number_count, 3); // Should find all three numbers: 123, 456, 789
1✔
360
    }
1✔
361

362
    #[test]
363
    fn test_pending_flag_priority() {
1✔
364
        // Defensive test: ensure that if both pending flags were somehow set,
365
        // we handle it gracefully (this shouldn't happen in normal operation)
366

367
        let json = br#"[{"key": 123}]"#;
1✔
368
        let reader = SliceReader::new(json);
1✔
369
        let mut buffer = [0u8; 256];
1✔
370
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
371

372
        // Parse normally - this should work fine and never set both flags
373
        let mut events = Vec::new();
1✔
374
        loop {
375
            match parser.next_event() {
7✔
376
                Ok(Event::EndDocument) => break,
1✔
377
                Ok(event) => events.push(format!("{:?}", event)),
6✔
378
                Err(e) => panic!("Flag priority test failed: {:?}", e),
×
379
            }
380
        }
381

382
        // Should successfully parse: StartArray, StartObject, Key, Number, EndObject, EndArray
383
        assert_eq!(events.len(), 6);
1✔
384
        assert!(events[3].contains("Number"));
1✔
385
        assert_eq!(&events[4], "EndObject");
1✔
386
        assert_eq!(&events[5], "EndArray");
1✔
387
    }
1✔
388

389
    #[test]
390
    fn test_direct_parser_array_of_strings() {
1✔
391
        let json = b"[\"first\", \"second\"]";
1✔
392
        let reader = SliceReader::new(json);
1✔
393
        let mut buffer = [0u8; 256];
1✔
394
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
395

396
        assert!(matches!(parser.next_event().unwrap(), Event::StartArray));
1✔
397

398
        if let Event::String(s1) = parser.next_event().unwrap() {
1✔
399
            assert_eq!(s1.as_str(), "first");
1✔
400
        } else {
401
            panic!("Expected String event");
×
402
        }
403

404
        if let Event::String(s2) = parser.next_event().unwrap() {
1✔
405
            assert_eq!(s2.as_str(), "second");
1✔
406
        } else {
407
            panic!("Expected String event");
×
408
        }
409

410
        assert!(matches!(parser.next_event().unwrap(), Event::EndArray));
1✔
411
    }
1✔
412

413
    #[test]
414
    fn test_direct_parser_object_with_keys() {
1✔
415
        let json = b"{\"name\": \"value\", \"count\": \"42\"}";
1✔
416
        let reader = SliceReader::new(json);
1✔
417
        let mut buffer = [0u8; 256];
1✔
418
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
419

420
        assert!(matches!(parser.next_event().unwrap(), Event::StartObject));
1✔
421

422
        // First key-value pair
423
        if let Event::Key(key1) = parser.next_event().unwrap() {
1✔
424
            assert_eq!(key1.as_str(), "name");
1✔
425
        } else {
426
            panic!("Expected Key event");
×
427
        }
428

429
        if let Event::String(val1) = parser.next_event().unwrap() {
1✔
430
            assert_eq!(val1.as_str(), "value");
1✔
431
        } else {
432
            panic!("Expected String event");
×
433
        }
434

435
        // Second key-value pair
436
        if let Event::Key(key2) = parser.next_event().unwrap() {
1✔
437
            assert_eq!(key2.as_str(), "count");
1✔
438
        } else {
439
            panic!("Expected Key event");
×
440
        }
441

442
        if let Event::String(val2) = parser.next_event().unwrap() {
1✔
443
            assert_eq!(val2.as_str(), "42");
1✔
444
        } else {
445
            panic!("Expected String event");
×
446
        }
447

448
        assert!(matches!(parser.next_event().unwrap(), Event::EndObject));
1✔
449
    }
1✔
450

451
    #[test]
452
    fn test_direct_parser_multiple_escapes() {
1✔
453
        let json = b"\"line1\\nline2\\ttab\\\"quote\"";
1✔
454
        let reader = SliceReader::new(json);
1✔
455
        let mut buffer = [0u8; 256];
1✔
456
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
457

458
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
459
            let content = json_string.as_str();
1✔
460
            // Check that escape sequences were properly processed
461
            let has_newline = content.contains('\n');
1✔
462
            let has_tab = content.contains('\t');
1✔
463
            let has_quote = content.contains('"');
1✔
464

465
            // These should be real control characters, not literal \n \t \"
466
            assert!(has_newline, "Should contain actual newline character");
1✔
467
            assert!(has_tab, "Should contain actual tab character");
1✔
468
            assert!(has_quote, "Should contain actual quote character");
1✔
469
        } else {
470
            panic!("Expected String event");
×
471
        }
472
    }
1✔
473

474
    #[test]
475
    fn test_direct_parser_unicode_escape() {
1✔
476
        let json = b"\"Hello \\u0041\\u03B1\""; // Hello A(alpha)
1✔
477
        let reader = SliceReader::new(json);
1✔
478
        let mut buffer = [0u8; 256];
1✔
479
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
480

481
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
482
            let content = json_string.as_str();
1✔
483
            // Should be "Hello A⍺" (with actual A and alpha characters)
484
            assert!(content.contains('A'));
1✔
485
            // Note: This test will initially fail until we implement Unicode escapes
486
        } else {
487
            panic!("Expected String event");
×
488
        }
489
    }
1✔
490

491
    #[test]
492
    fn test_direct_parser_boolean_true() {
1✔
493
        let json = b"true";
1✔
494
        let reader = SliceReader::new(json);
1✔
495
        let mut buffer = [0u8; 256];
1✔
496
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
497

498
        let event = parser.next_event().unwrap();
1✔
499
        assert_eq!(event, Event::Bool(true));
1✔
500

501
        let event = parser.next_event().unwrap();
1✔
502
        assert_eq!(event, Event::EndDocument);
1✔
503
    }
1✔
504

505
    #[test]
506
    fn test_direct_parser_boolean_false() {
1✔
507
        let json = b"false";
1✔
508
        let reader = SliceReader::new(json);
1✔
509
        let mut buffer = [0u8; 256];
1✔
510
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
511

512
        let event = parser.next_event().unwrap();
1✔
513
        assert_eq!(event, Event::Bool(false));
1✔
514

515
        let event = parser.next_event().unwrap();
1✔
516
        assert_eq!(event, Event::EndDocument);
1✔
517
    }
1✔
518

519
    #[test]
520
    fn test_direct_parser_null() {
1✔
521
        let json = b"null";
1✔
522
        let reader = SliceReader::new(json);
1✔
523
        let mut buffer = [0u8; 256];
1✔
524
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
525

526
        let event = parser.next_event().unwrap();
1✔
527
        assert_eq!(event, Event::Null);
1✔
528

529
        let event = parser.next_event().unwrap();
1✔
530
        assert_eq!(event, Event::EndDocument);
1✔
531
    }
1✔
532

533
    #[test]
534
    fn test_direct_parser_booleans_in_array() {
1✔
535
        let json = b"[true, false, null]";
1✔
536
        let reader = SliceReader::new(json);
1✔
537
        let mut buffer = [0u8; 256];
1✔
538
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
539

540
        assert_eq!(parser.next_event().unwrap(), Event::StartArray);
1✔
541
        assert_eq!(parser.next_event().unwrap(), Event::Bool(true));
1✔
542
        assert_eq!(parser.next_event().unwrap(), Event::Bool(false));
1✔
543
        assert_eq!(parser.next_event().unwrap(), Event::Null);
1✔
544
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1✔
545
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
546
    }
1✔
547

548
    #[test]
549
    fn test_direct_parser_number_simple() {
1✔
550
        let json = b"42";
1✔
551
        let reader = SliceReader::new(json);
1✔
552
        let mut buffer = [0u8; 256];
1✔
553
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
554

555
        let event = parser.next_event().unwrap();
1✔
556
        if let Event::Number(json_number) = event {
1✔
557
            assert_eq!(json_number.as_str(), "42");
1✔
558
        } else {
559
            panic!("Expected Number event, got: {:?}", event);
×
560
        }
561

562
        let event = parser.next_event().unwrap();
1✔
563
        assert_eq!(event, Event::EndDocument);
1✔
564
    }
1✔
565

566
    #[test]
567
    fn test_direct_parser_number_negative() {
1✔
568
        let json = b"-123";
1✔
569
        let reader = SliceReader::new(json);
1✔
570
        let mut buffer = [0u8; 256];
1✔
571
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
572

573
        let event = parser.next_event().unwrap();
1✔
574
        if let Event::Number(json_number) = event {
1✔
575
            assert_eq!(json_number.as_str(), "-123");
1✔
576
        } else {
577
            panic!("Expected Number event, got: {:?}", event);
×
578
        }
579

580
        let event = parser.next_event().unwrap();
1✔
581
        assert_eq!(event, Event::EndDocument);
1✔
582
    }
1✔
583

584
    #[test]
585
    fn test_direct_parser_number_float() {
1✔
586
        let json = b"3.14159";
1✔
587
        let reader = SliceReader::new(json);
1✔
588
        let mut buffer = [0u8; 256];
1✔
589
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
590

591
        #[cfg(feature = "float-error")]
592
        {
593
            // float-error configuration should return an error for float values
594
            let result = parser.next_event();
595
            assert!(
596
                result.is_err(),
597
                "Expected error for float with float-error configuration"
598
            );
599
            return;
600
        }
601

602
        #[cfg(not(feature = "float-error"))]
603
        {
604
            let event = parser.next_event().unwrap();
1✔
605
            if let Event::Number(json_number) = event {
1✔
606
                assert_eq!(json_number.as_str(), "3.14159");
1✔
607
            } else {
608
                panic!("Expected Number event, got: {:?}", event);
×
609
            }
610

611
            let event = parser.next_event().unwrap();
1✔
612
            assert_eq!(event, Event::EndDocument);
1✔
613
        }
614
    }
1✔
615

616
    #[test]
617
    fn test_direct_parser_numbers_in_array() {
1✔
618
        #[cfg(feature = "float-error")]
619
        let json = b"[42, -7]"; // No floats for float-error config
620
        #[cfg(not(feature = "float-error"))]
621
        let json = b"[42, -7, 3.14]"; // Include float for other configs
1✔
622

623
        let reader = SliceReader::new(json);
1✔
624
        let mut buffer = [0u8; 256];
1✔
625
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
626

627
        assert_eq!(parser.next_event().unwrap(), Event::StartArray);
1✔
628

629
        let event = parser.next_event().unwrap();
1✔
630
        if let Event::Number(json_number) = event {
1✔
631
            assert_eq!(json_number.as_str(), "42");
1✔
632
        } else {
633
            panic!("Expected Number event, got: {:?}", event);
×
634
        }
635

636
        let event = parser.next_event().unwrap();
1✔
637
        if let Event::Number(json_number) = event {
1✔
638
            assert_eq!(json_number.as_str(), "-7");
1✔
639
        } else {
640
            panic!("Expected Number event, got: {:?}", event);
×
641
        }
642

643
        #[cfg(not(feature = "float-error"))]
644
        {
645
            let event = parser.next_event().unwrap();
1✔
646
            if let Event::Number(json_number) = event {
1✔
647
                assert_eq!(json_number.as_str(), "3.14");
1✔
648
            } else {
649
                panic!("Expected Number event, got: {:?}", event);
×
650
            }
651
        }
652

653
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1✔
654
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
655
    }
1✔
656

657
    #[test]
658
    fn test_direct_parser_numbers_in_object() {
1✔
659
        #[cfg(feature = "float-error")]
660
        let json = b"{\"count\": 42, \"score\": -7}"; // No floats for float-error config
661
        #[cfg(not(feature = "float-error"))]
662
        let json = b"{\"count\": 42, \"score\": -7.5}"; // Include float for other configs
1✔
663

664
        let reader = SliceReader::new(json);
1✔
665
        let mut buffer = [0u8; 256];
1✔
666
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
667

668
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
669

670
        // First key-value pair
671
        if let Event::Key(key1) = parser.next_event().unwrap() {
1✔
672
            assert_eq!(key1.as_str(), "count");
1✔
673
        } else {
674
            panic!("Expected Key event");
×
675
        }
676

677
        if let Event::Number(val1) = parser.next_event().unwrap() {
1✔
678
            assert_eq!(val1.as_str(), "42");
1✔
679
        } else {
680
            panic!("Expected Number event");
×
681
        }
682

683
        // Second key-value pair
684
        if let Event::Key(key2) = parser.next_event().unwrap() {
1✔
685
            assert_eq!(key2.as_str(), "score");
1✔
686
        } else {
687
            panic!("Expected Key event");
×
688
        }
689

690
        if let Event::Number(val2) = parser.next_event().unwrap() {
1✔
691
            #[cfg(feature = "float-error")]
692
            assert_eq!(val2.as_str(), "-7");
693
            #[cfg(not(feature = "float-error"))]
694
            assert_eq!(val2.as_str(), "-7.5");
1✔
695
        } else {
696
            panic!("Expected Number event");
×
697
        }
698

699
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
700
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
701
    }
1✔
702

703
    #[test]
704
    fn test_direct_parser_no_float_configuration() {
1✔
705
        // Test that StreamParser properly uses unified number parsing with no-float config
706
        let json = br#"{"integer": 42, "float": 3.14, "scientific": 1e3}"#;
1✔
707
        let reader = SliceReader::new(json);
1✔
708
        let mut buffer = [0u8; 256];
1✔
709
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
710

711
        // Parse through the JSON and verify number handling
712
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
713

714
        // Integer key-value
715
        assert_eq!(
1✔
716
            parser.next_event().unwrap(),
1✔
717
            Event::Key(crate::String::Borrowed("integer"))
718
        );
719
        if let Event::Number(num) = parser.next_event().unwrap() {
1✔
720
            assert_eq!(num.as_str(), "42");
1✔
721
            match num.parsed() {
1✔
722
                NumberResult::Integer(i) => assert_eq!(*i, 42),
1✔
723
                _ => panic!("Expected integer parsing"),
×
724
            }
725
        } else {
726
            panic!("Expected Number event");
×
727
        }
728

729
        // Float key-value - behavior varies by configuration
730
        assert_eq!(
1✔
731
            parser.next_event().unwrap(),
1✔
732
            Event::Key(crate::String::Borrowed("float"))
733
        );
734

735
        #[cfg(feature = "float-error")]
736
        {
737
            // float-error should return an error when encountering floats
738
            let result = parser.next_event();
739
            assert!(
740
                result.is_err(),
741
                "Expected error for float with float-error configuration"
742
            );
743
            // Test ends here for float-error - no more processing needed
744
        }
745

746
        #[cfg(not(feature = "float-error"))]
747
        {
748
            if let Event::Number(num) = parser.next_event().unwrap() {
1✔
749
                assert_eq!(num.as_str(), "3.14");
1✔
750
                // In no-float configuration, this should be FloatDisabled
751
                match num.parsed() {
1✔
752
                    #[cfg(not(feature = "float"))]
753
                    NumberResult::FloatDisabled => {
754
                        // This is expected in no-float build
755
                    }
756
                    #[cfg(feature = "float")]
757
                    NumberResult::Float(f) => {
1✔
758
                        // This is expected in float-enabled build
759
                        assert!((f - 3.14).abs() < 0.01);
1✔
760
                    }
761
                    #[cfg(feature = "float-skip")]
762
                    NumberResult::FloatSkipped => {
763
                        // This is expected in float-skip build
764
                    }
765
                    #[cfg(feature = "float-truncate")]
766
                    NumberResult::FloatTruncated(i) => {
767
                        // This is expected in float-truncate build (3.14 -> 3)
768
                        assert_eq!(*i, 3);
769
                    }
770
                    _ => panic!("Unexpected number parsing result for float"),
×
771
                }
772
            } else {
773
                panic!("Expected Number event");
×
774
            }
775

776
            // Scientific notation handling varies by float configuration
777
            assert_eq!(
1✔
778
                parser.next_event().unwrap(),
1✔
779
                Event::Key(crate::String::Borrowed("scientific"))
780
            );
781

782
            // float-truncate rejects scientific notation, so test should end early for that config
783
            #[cfg(feature = "float-truncate")]
784
            {
785
                // float-truncate rejects scientific notation since it would require float math
786
                let result = parser.next_event();
787
                assert!(
788
                    result.is_err(),
789
                    "Expected error for scientific notation with float-truncate"
790
                );
791
                // Test ends here for float-truncate - no more processing needed
792
            }
793

794
            #[cfg(not(feature = "float-truncate"))]
795
            {
796
                if let Event::Number(num) = parser.next_event().unwrap() {
1✔
797
                    assert_eq!(num.as_str(), "1e3");
1✔
798
                    match num.parsed() {
1✔
799
                        #[cfg(not(feature = "float"))]
800
                        NumberResult::FloatDisabled => {
801
                            // This is expected in no-float build - raw string preserved for manual parsing
802
                        }
803
                        #[cfg(feature = "float-skip")]
804
                        NumberResult::FloatSkipped => {
805
                            // This is expected in float-skip build
806
                        }
807
                        #[cfg(feature = "float")]
808
                        NumberResult::Float(f) => {
1✔
809
                            // This is expected in float-enabled build
810
                            assert!((f - 1000.0).abs() < f64::EPSILON);
1✔
811
                        }
812
                        _ => panic!("Unexpected number parsing result for scientific notation"),
×
813
                    }
814
                } else {
815
                    panic!("Expected Number event");
×
816
                }
817

818
                assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
819
                assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
820
            }
821
        }
822
    }
1✔
823

824
    #[test]
825
    fn test_number_parsing_delimiter_exclusion() {
1✔
826
        // Test that numbers don't include trailing delimiters in various contexts
827

828
        // Test 1: Number followed by array end
829
        let json1 = b"[123]";
1✔
830
        let reader1 = SliceReader::new(json1);
1✔
831
        let mut buffer1 = [0u8; 256];
1✔
832
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
833

834
        assert!(matches!(parser1.next_event().unwrap(), Event::StartArray));
1✔
835
        if let Event::Number(num) = parser1.next_event().unwrap() {
1✔
836
            assert_eq!(
1✔
837
                num.as_str(),
1✔
838
                "123",
839
                "Number should not include trailing delimiter ']'"
×
840
            );
841
        } else {
842
            panic!("Expected Number event");
×
843
        }
844
        assert!(matches!(parser1.next_event().unwrap(), Event::EndArray));
1✔
845

846
        // Test 2: Number followed by object end
847
        let json2 = b"{\"key\":456}";
1✔
848
        let reader2 = SliceReader::new(json2);
1✔
849
        let mut buffer2 = [0u8; 256];
1✔
850
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
851

852
        assert!(matches!(parser2.next_event().unwrap(), Event::StartObject));
1✔
853
        assert!(matches!(parser2.next_event().unwrap(), Event::Key(_)));
1✔
854
        if let Event::Number(num) = parser2.next_event().unwrap() {
1✔
855
            assert_eq!(
1✔
856
                num.as_str(),
1✔
857
                "456",
858
                "Number should not include trailing delimiter '}}'"
×
859
            );
860
        } else {
861
            panic!("Expected Number event");
×
862
        }
863
        assert!(matches!(parser2.next_event().unwrap(), Event::EndObject));
1✔
864

865
        // Test 3: Number followed by comma in array
866
        let json3 = b"[789,10]";
1✔
867
        let reader3 = SliceReader::new(json3);
1✔
868
        let mut buffer3 = [0u8; 256];
1✔
869
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
870

871
        assert!(matches!(parser3.next_event().unwrap(), Event::StartArray));
1✔
872
        if let Event::Number(num1) = parser3.next_event().unwrap() {
1✔
873
            assert_eq!(
1✔
874
                num1.as_str(),
1✔
875
                "789",
876
                "First number should not include trailing delimiter ','"
×
877
            );
878
        } else {
879
            panic!("Expected first Number event");
×
880
        }
881
        if let Event::Number(num2) = parser3.next_event().unwrap() {
1✔
882
            assert_eq!(
1✔
883
                num2.as_str(),
1✔
884
                "10",
885
                "Second number should not include trailing delimiter ']'"
×
886
            );
887
        } else {
888
            panic!("Expected second Number event");
×
889
        }
890
        assert!(matches!(parser3.next_event().unwrap(), Event::EndArray));
1✔
891

892
        // Test 4: Number followed by comma in object
893
        let json4 = b"{\"a\":11,\"b\":22}";
1✔
894
        let reader4 = SliceReader::new(json4);
1✔
895
        let mut buffer4 = [0u8; 256];
1✔
896
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
1✔
897

898
        assert!(matches!(parser4.next_event().unwrap(), Event::StartObject));
1✔
899
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1✔
900
        if let Event::Number(num1) = parser4.next_event().unwrap() {
1✔
901
            assert_eq!(
1✔
902
                num1.as_str(),
1✔
903
                "11",
904
                "First number should not include trailing delimiter ','"
×
905
            );
906
        } else {
907
            panic!("Expected first Number event");
×
908
        }
909
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1✔
910
        if let Event::Number(num2) = parser4.next_event().unwrap() {
1✔
911
            assert_eq!(
1✔
912
                num2.as_str(),
1✔
913
                "22",
914
                "Second number should not include trailing delimiter '}}'"
×
915
            );
916
        } else {
917
            panic!("Expected second Number event");
×
918
        }
919
        assert!(matches!(parser4.next_event().unwrap(), Event::EndObject));
1✔
920

921
        // Test 5: Standalone number at end of document (should include full content)
922
        let json5 = b"999";
1✔
923
        let reader5 = SliceReader::new(json5);
1✔
924
        let mut buffer5 = [0u8; 256];
1✔
925
        let mut parser5 = TestStreamParser::new(reader5, &mut buffer5);
1✔
926

927
        if let Event::Number(num) = parser5.next_event().unwrap() {
1✔
928
            assert_eq!(
1✔
929
                num.as_str(),
1✔
930
                "999",
931
                "Standalone number should include full content"
×
932
            );
933
        } else {
934
            panic!("Expected Number event");
×
935
        }
936
        assert!(matches!(parser5.next_event().unwrap(), Event::EndDocument));
1✔
937

938
        // Test 6: Negative numbers with delimiters
939
        let json6 = b"[-42,33]";
1✔
940
        let reader6 = SliceReader::new(json6);
1✔
941
        let mut buffer6 = [0u8; 256];
1✔
942
        let mut parser6 = TestStreamParser::new(reader6, &mut buffer6);
1✔
943

944
        assert!(matches!(parser6.next_event().unwrap(), Event::StartArray));
1✔
945
        if let Event::Number(num1) = parser6.next_event().unwrap() {
1✔
946
            assert_eq!(
1✔
947
                num1.as_str(),
1✔
948
                "-42",
949
                "Negative number should not include trailing delimiter ','"
×
950
            );
951
        } else {
952
            panic!("Expected first Number event");
×
953
        }
954
        if let Event::Number(num2) = parser6.next_event().unwrap() {
1✔
955
            assert_eq!(
1✔
956
                num2.as_str(),
1✔
957
                "33",
958
                "Second number should not include trailing delimiter ']'"
×
959
            );
960
        } else {
961
            panic!("Expected second Number event");
×
962
        }
963
        assert!(matches!(parser6.next_event().unwrap(), Event::EndArray));
1✔
964

965
        // Test 7: Decimal numbers with delimiters (if float enabled)
966
        #[cfg(not(feature = "float-error"))]
967
        {
968
            let json7 = b"[3.14,2.71]";
1✔
969
            let reader7 = SliceReader::new(json7);
1✔
970
            let mut buffer7 = [0u8; 256];
1✔
971
            let mut parser7 = TestStreamParser::new(reader7, &mut buffer7);
1✔
972

973
            assert!(matches!(parser7.next_event().unwrap(), Event::StartArray));
1✔
974
            if let Event::Number(num1) = parser7.next_event().unwrap() {
1✔
975
                assert_eq!(
1✔
976
                    num1.as_str(),
1✔
977
                    "3.14",
978
                    "Decimal number should not include trailing delimiter ','"
×
979
                );
980
            } else {
981
                panic!("Expected first Number event");
×
982
            }
983
            if let Event::Number(num2) = parser7.next_event().unwrap() {
1✔
984
                assert_eq!(
1✔
985
                    num2.as_str(),
1✔
986
                    "2.71",
987
                    "Second decimal number should not include trailing delimiter ']'"
×
988
                );
989
            } else {
990
                panic!("Expected second Number event");
×
991
            }
992
            assert!(matches!(parser7.next_event().unwrap(), Event::EndArray));
1✔
993
        }
994
    }
1✔
995

996
    #[test]
997
    fn test_escape_buffer_functions() {
1✔
998
        // Test the uncovered escape processing functions
999
        let json_stream = br#"{"escaped": "test\nstring"}"#;
1✔
1000
        let mut buffer = [0u8; 1024];
1✔
1001
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1✔
1002

1003
        // These functions are private but we can test them through the public API
1004
        // The escape processing should trigger the uncovered functions
1005
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1006
        assert_eq!(
1✔
1007
            parser.next_event().unwrap(),
1✔
1008
            Event::Key(crate::String::Borrowed("escaped"))
1009
        );
1010

1011
        // This should trigger append_byte_to_escape_buffer and queue_unescaped_reset
1012
        if let Event::String(s) = parser.next_event().unwrap() {
1✔
1013
            assert_eq!(s.as_ref(), "test\nstring"); // Escape sequence should be processed
1✔
1014
        } else {
1015
            panic!("Expected String event with escape sequence");
×
1016
        }
1017

1018
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1019
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1020
    }
1✔
1021

1022
    #[test]
1023
    fn test_slice_reader_constructor() {
1✔
1024
        // Test the uncovered SliceReader::new function
1025
        let data = b"test data";
1✔
1026
        let reader = SliceReader::new(data);
1✔
1027
        assert_eq!(reader.data, data);
1✔
1028
        assert_eq!(reader.position, 0);
1✔
1029
    }
1✔
1030

1031
    #[test]
1032
    fn test_complex_escape_sequences() {
1✔
1033
        // Test more complex escape processing to cover the escape buffer functions
1034
        let json_stream = br#"{"multi": "line1\nline2\ttab\r\n"}"#;
1✔
1035
        let mut buffer = [0u8; 1024];
1✔
1036
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1✔
1037

1038
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1039
        assert_eq!(
1✔
1040
            parser.next_event().unwrap(),
1✔
1041
            Event::Key(crate::String::Borrowed("multi"))
1042
        );
1043

1044
        // This should exercise the escape buffer processing extensively
1045
        if let Event::String(s) = parser.next_event().unwrap() {
1✔
1046
            assert_eq!(s.as_ref(), "line1\nline2\ttab\r\n");
1✔
1047
        } else {
1048
            panic!("Expected String event");
×
1049
        }
1050

1051
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1052
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1053
    }
1✔
1054

1055
    /// Helper function to test escape sequence parsing with specific buffer size
1056
    fn test_simple_escape_with_buffer_size(buffer_size: usize) -> Result<(), ParseError> {
3✔
1057
        // DEBUG TEST: Simple escape sequence should need minimal buffer
1058
        // JSON: ["hello\\"] = 10 bytes total, should work with ~7 byte buffer
1059
        let json_stream = br#"["hello\\"]"#;
3✔
1060

1061
        let mut buffer = vec![0u8; buffer_size];
3✔
1062
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
3✔
1063

1064
        // Array start
1065
        assert!(matches!(parser.next_event()?, Event::StartArray));
3✔
1066

1067
        // String with escape
1068
        assert!(matches!(parser.next_event()?, Event::String(s) if s.as_str() == "hello\\"));
3✔
1069

1070
        // Array end
1071
        assert!(matches!(parser.next_event()?, Event::EndArray));
2✔
1072

1073
        // End document
1074
        assert!(matches!(parser.next_event()?, Event::EndDocument));
2✔
1075

1076
        Ok(())
2✔
1077
    }
3✔
1078

1079
    #[test]
1080
    fn test_minimal_buffer_simple_escape_1() {
1✔
1081
        // Buffer size 4 - token "hello\\" (8 bytes) too large for buffer (4 bytes)
1082
        // This should be InputBufferFull, not ScratchBufferFull
1083
        assert!(matches!(
1✔
1084
            test_simple_escape_with_buffer_size(4),
1✔
1085
            Err(ParseError::InputBufferFull)
1086
        ));
1087
    }
1✔
1088

1089
    #[test]
1090
    fn test_minimal_buffer_simple_escape_2() {
1✔
1091
        // Buffer size 12 - test if larger buffer avoids compaction bugs
1092
        test_simple_escape_with_buffer_size(12)
1✔
1093
            .expect("12-byte buffer should be sufficient for simple escape");
1✔
1094
    }
1✔
1095

1096
    #[test]
1097
    fn test_minimal_buffer_simple_escape_3() {
1✔
1098
        // Buffer size 24 - known working boundary from stress tests
1099
        test_simple_escape_with_buffer_size(24).expect("24-byte buffer should definitely work");
1✔
1100
    }
1✔
1101

1102
    #[test]
1103
    fn test_surrogate_pair_buffer_boundary_cases() {
1✔
1104
        // Test 7: Surrogate pair split across very small buffer chunks
1105
        let input7 = r#"["\uD801\uDC37"]"#;
1✔
1106
        let mut buffer7 = [0u8; 16]; // Small buffer
1✔
1107
        let reader7 = crate::chunk_reader::ChunkReader::new(input7.as_bytes(), 3); // Tiny chunks
1✔
1108
        let mut parser7 = StreamParser::<_, DefaultConfig>::with_config(reader7, &mut buffer7);
1✔
1109
        assert_eq!(parser7.next_event(), Ok(Event::StartArray));
1✔
1110
        match parser7.next_event() {
1✔
1111
            Ok(Event::String(s)) => {
1✔
1112
                let content = match s {
1✔
UNCOV
1113
                    crate::String::Borrowed(c) => c,
×
1114
                    crate::String::Unescaped(c) => c,
1✔
1115
                };
1116
                assert_eq!(content, "𐐷");
1✔
1117
            }
UNCOV
1118
            other => panic!(
×
1119
                "Expected String with surrogate pair across buffer boundary, got: {:?}",
×
1120
                other
1121
            ),
1122
        }
1123

1124
        // Test 8: Surrogate pair with small buffer (still needs minimum space)
1125
        let input8 = r#"["\uD801\uDC37"]"#;
1✔
1126
        let mut buffer8 = [0u8; 32]; // Small but sufficient buffer
1✔
1127
        let reader8 = crate::chunk_reader::ChunkReader::new(input8.as_bytes(), 6); // Split at surrogate boundary
1✔
1128
        let mut parser8 = StreamParser::<_, DefaultConfig>::with_config(reader8, &mut buffer8);
1✔
1129
        assert_eq!(parser8.next_event(), Ok(Event::StartArray));
1✔
1130
        match parser8.next_event() {
1✔
1131
            Ok(Event::String(s)) => {
1✔
1132
                let content = match s {
1✔
UNCOV
1133
                    crate::String::Borrowed(c) => c,
×
1134
                    crate::String::Unescaped(c) => c,
1✔
1135
                };
1136
                assert_eq!(content, "𐐷");
1✔
1137
            }
UNCOV
1138
            other => panic!(
×
1139
                "Expected String with surrogate pair at small buffer, got: {:?}",
×
1140
                other
1141
            ),
1142
        }
1143
    }
1✔
1144
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc