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

kaidokert / picojson-rs / 16309731743

16 Jul 2025 03:35AM UTC coverage: 94.287% (+0.4%) from 93.864%
16309731743

Pull #60

github

web-flow
Merge eb993d70a into d7962e604
Pull Request #60: Clean refactor

504 of 541 new or added lines in 9 files covered. (93.16%)

5 existing lines in 2 files now uncovered.

4704 of 4989 relevant lines covered (94.29%)

741.71 hits per line

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

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

3
use crate::event_processor::{ContentExtractor, EscapeHandler};
4
use crate::parse_error::ParseError;
5
use crate::parser_core::ParserCore;
6
use crate::shared::{ByteProvider, Event, State};
7
use crate::stream_content_builder::StreamContentBuilder;
8
use crate::{ujson, PullParser};
9

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

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

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

27
/// A pull parser that parses JSON from a stream.
28
///
29
/// Generic over BitStackConfig for configurable nesting depth.
30
/// It is designed to be used with the [Reader] trait, which is used to read data from a stream.
31
///
32
pub struct StreamParser<'b, R: Reader, C: BitStackConfig = DefaultConfig> {
33
    /// The shared parser core that handles the unified event processing loop
34
    parser_core: ParserCore<C::Bucket, C::Counter>,
35
    /// The unified provider that handles both content building and reader access
36
    /// This allows us to use the same unified pattern as SliceParser
37
    provider: StreamParserProvider<'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,034✔
47
        Self::with_config(reader, buffer)
1,034✔
48
    }
1,034✔
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,076✔
71
        Self {
1,076✔
72
            parser_core: ParserCore::new(),
1,076✔
73
            provider: StreamParserProvider::new(reader, buffer),
1,076✔
74
        }
1,076✔
75
    }
1,076✔
76
}
77

78
/// Implement the required traits for StreamParser to work with unified ParserCore
79
/// This provider handles the StreamParser-specific operations needed by the unified parser core
80
/// It bridges the gap between the generic ParserCore and the StreamParser's specific requirements
81
/// for streaming input and buffer management
82
/// The provider contains mutable references to the StreamParser's internal state
83
/// which allows the unified parser core to control the parsing process
84
pub struct StreamParserProvider<'b, R: Reader> {
85
    content_builder: StreamContentBuilder<'b>,
86
    reader: R,
87
    finished: bool,
88
}
89

90
impl<'b, R: Reader> StreamParserProvider<'b, R> {
91
    pub fn new(reader: R, buffer: &'b mut [u8]) -> Self {
1,076✔
92
        Self {
1,076✔
93
            content_builder: StreamContentBuilder::new(buffer),
1,076✔
94
            reader,
1,076✔
95
            finished: false,
1,076✔
96
        }
1,076✔
97
    }
1,076✔
98
}
99

100
impl<R: Reader> ByteProvider for StreamParserProvider<'_, R> {
101
    fn next_byte(&mut self) -> Result<Option<u8>, ParseError> {
19,283✔
102
        // If buffer is empty, try to fill it first
103
        if self.content_builder.stream_buffer().is_empty() {
19,283✔
104
            self.content_builder
6,860✔
105
                .fill_buffer_from_reader(&mut self.reader)?;
6,860✔
106
        }
12,423✔
107

108
        // If still empty after fill attempt, we're at EOF
109
        if self.content_builder.stream_buffer().is_empty() {
18,754✔
110
            if !self.finished {
492✔
111
                self.finished = true;
492✔
112
                self.content_builder.set_finished(true);
492✔
113
            }
492✔
114
            return Ok(None);
492✔
115
        }
18,262✔
116

117
        // Get byte and advance
118
        let byte = self.content_builder.stream_buffer().current_byte()?;
18,262✔
119
        self.content_builder.stream_buffer_mut().advance()?;
18,262✔
120
        Ok(Some(byte))
18,262✔
121
    }
19,283✔
122
}
123

124
impl<R: Reader> EscapeHandler for StreamParserProvider<'_, R> {
125
    fn parser_state(&self) -> &State {
2,797✔
126
        self.content_builder.parser_state()
2,797✔
127
    }
2,797✔
128

129
    fn process_unicode_escape_with_collector(&mut self) -> Result<(), ParseError> {
166✔
130
        self.content_builder.process_unicode_escape_with_collector()
166✔
131
    }
166✔
132

133
    fn handle_simple_escape_char(&mut self, escape_char: u8) -> Result<(), ParseError> {
668✔
134
        self.content_builder.handle_simple_escape_char(escape_char)
668✔
135
    }
668✔
136

137
    fn begin_escape_sequence(&mut self) -> Result<(), ParseError> {
894✔
138
        self.content_builder.begin_escape_sequence()
894✔
139
    }
894✔
140

141
    fn begin_unicode_escape(&mut self) -> Result<(), ParseError> {
184✔
142
        self.content_builder.begin_unicode_escape()
184✔
143
    }
184✔
144
}
145

146
impl<R: Reader> ContentExtractor for StreamParserProvider<'_, R> {
147
    fn parser_state_mut(&mut self) -> &mut State {
2,313✔
148
        self.content_builder.parser_state_mut()
2,313✔
149
    }
2,313✔
150

151
    fn current_position(&self) -> usize {
1,430✔
152
        self.content_builder.current_position()
1,430✔
153
    }
1,430✔
154

155
    fn begin_string_content(&mut self, pos: usize) {
988✔
156
        self.content_builder.begin_string_content(pos);
988✔
157
    }
988✔
158

159
    fn unicode_escape_collector_mut(
1,487✔
160
        &mut self,
1,487✔
161
    ) -> &mut crate::escape_processor::UnicodeEscapeCollector {
1,487✔
162
        self.content_builder.unicode_escape_collector_mut()
1,487✔
163
    }
1,487✔
164

165
    fn extract_string_content(&mut self, start_pos: usize) -> Result<Event<'_, '_>, ParseError> {
380✔
166
        self.content_builder.extract_string_content(start_pos)
380✔
167
    }
380✔
168

169
    fn extract_key_content(&mut self, start_pos: usize) -> Result<Event<'_, '_>, ParseError> {
253✔
170
        self.content_builder.extract_key_content(start_pos)
253✔
171
    }
253✔
172

173
    fn extract_number(
250✔
174
        &mut self,
250✔
175
        start_pos: usize,
250✔
176
        from_container_end: bool,
250✔
177
        finished: bool,
250✔
178
    ) -> Result<Event<'_, '_>, ParseError> {
250✔
179
        self.content_builder
250✔
180
            .extract_number(start_pos, from_container_end, finished)
250✔
181
    }
250✔
182

183
    /// Override the default validate_and_extract_number to use the finished state
184
    fn validate_and_extract_number(
250✔
185
        &mut self,
250✔
186
        from_container_end: bool,
250✔
187
    ) -> Result<Event<'_, '_>, ParseError> {
250✔
188
        let start_pos = match *self.parser_state() {
250✔
189
            crate::shared::State::Number(pos) => pos,
250✔
NEW
190
            _ => return Err(crate::shared::UnexpectedState::StateMismatch.into()),
×
191
        };
192

193
        *self.parser_state_mut() = crate::shared::State::None;
250✔
194
        // Use the finished-aware extract_number method
195
        self.extract_number(start_pos, from_container_end, self.finished)
250✔
196
    }
250✔
197
}
198

199
/// Shared methods for StreamParser with any BitStackConfig
200
impl<R: Reader, C: BitStackConfig> StreamParser<'_, R, C> {
201
    /// Get the next JSON event from the stream
202
    fn next_event_impl(&mut self) -> Result<Event<'_, '_>, ParseError> {
4,949✔
203
        // Use the unified ParserCore implementation with StreamParser-specific timing
204
        // StreamParser needs byte accumulation for string parsing
205
        self.parser_core.next_event_impl(
4,949✔
206
            &mut self.provider,
4,949✔
207
            crate::parser_core::EscapeTiming::OnEnd,
4,949✔
208
            |provider, byte| {
11,209✔
209
                // Delegate to the StreamContentBuilder's byte accumulation logic
210
                provider.content_builder.handle_byte_accumulation(byte)
11,209✔
211
            },
11,209✔
212
        )
213
    }
4,949✔
214

215
    // The compaction and helper methods are now handled by the provider
216
    // These methods can be removed since they're not needed with the new architecture
217
}
218

219
impl<R: Reader, C: BitStackConfig> PullParser for StreamParser<'_, R, C> {
220
    fn next_event(&mut self) -> Result<Event<'_, '_>, ParseError> {
4,953✔
221
        // Check if we're already finished (similar to SliceParser's is_past_end check)
222
        if self.provider.finished {
4,953✔
223
            return Ok(Event::EndDocument);
4✔
224
        }
4,949✔
225

226
        self.provider
4,949✔
227
            .content_builder
4,949✔
228
            .apply_unescaped_reset_if_queued();
4,949✔
229

230
        self.next_event_impl()
4,949✔
231
    }
4,953✔
232
}
233

234
#[cfg(test)]
235
mod tests {
236
    use super::*;
237

238
    /// Simple test reader that reads from a byte slice
239
    pub struct SliceReader<'a> {
240
        data: &'a [u8],
241
        position: usize,
242
    }
243

244
    impl<'a> SliceReader<'a> {
245
        pub fn new(data: &'a [u8]) -> Self {
39✔
246
            Self { data, position: 0 }
39✔
247
        }
39✔
248
    }
249

250
    impl Reader for SliceReader<'_> {
251
        type Error = ();
252

253
        fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
65✔
254
            let remaining = self.data.len().saturating_sub(self.position);
65✔
255
            if remaining == 0 {
65✔
256
                return Ok(0); // EOF
26✔
257
            }
39✔
258

259
            let to_copy = remaining.min(buf.len());
39✔
260
            let end_pos = self.position.saturating_add(to_copy);
39✔
261
            if let (Some(dest), Some(src)) = (
39✔
262
                buf.get_mut(..to_copy),
39✔
263
                self.data.get(self.position..end_pos),
39✔
264
            ) {
265
                dest.copy_from_slice(src);
39✔
266
                self.position = end_pos;
39✔
267
                Ok(to_copy)
39✔
268
            } else {
269
                Err(())
×
270
            }
271
        }
65✔
272
    }
273

274
    type TestStreamParser<'b> = StreamParser<'b, SliceReader<'static>>;
275

276
    #[test]
277
    fn test_direct_parser_simple_object() {
1✔
278
        let json = b"{}";
1✔
279
        let reader = SliceReader::new(json);
1✔
280
        let mut buffer = [0u8; 256];
1✔
281
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
282

283
        // Should get ObjectStart
284
        let event = parser.next_event().unwrap();
1✔
285
        assert!(matches!(event, Event::StartObject));
1✔
286

287
        // Should get ObjectEnd
288
        let event = parser.next_event().unwrap();
1✔
289
        assert!(matches!(event, Event::EndObject));
1✔
290

291
        // Should get EndDocument
292
        let event = parser.next_event().unwrap();
1✔
293
        assert!(matches!(event, Event::EndDocument));
1✔
294
    }
1✔
295

296
    #[test]
297
    fn test_direct_parser_simple_array() {
1✔
298
        let json = b"[]";
1✔
299
        let reader = SliceReader::new(json);
1✔
300
        let mut buffer = [0u8; 256];
1✔
301
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
302

303
        // Should get ArrayStart
304
        let event = parser.next_event().unwrap();
1✔
305
        assert!(matches!(event, Event::StartArray));
1✔
306

307
        // Should get ArrayEnd
308
        let event = parser.next_event().unwrap();
1✔
309
        assert!(matches!(event, Event::EndArray));
1✔
310

311
        // Should get EndDocument
312
        let event = parser.next_event().unwrap();
1✔
313
        assert!(matches!(event, Event::EndDocument));
1✔
314
    }
1✔
315

316
    #[test]
317
    fn test_direct_parser_simple_escape() {
1✔
318
        let json = b"\"hello\\nworld\"";
1✔
319
        let reader = SliceReader::new(json);
1✔
320
        let mut buffer = [0u8; 256];
1✔
321
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
322

323
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
324
            assert_eq!(json_string.as_str(), "hello\nworld");
1✔
325
        } else {
326
            panic!("Expected String event");
×
327
        }
328
    }
1✔
329

330
    #[test]
331
    fn test_pending_state_edge_cases() {
1✔
332
        // Test 1: Complex nested container endings
333
        let json1 = br#"{"a": {"b": [{"c": 123}]}}"#;
1✔
334
        let reader1 = SliceReader::new(json1);
1✔
335
        let mut buffer1 = [0u8; 256];
1✔
336
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
337

338
        let mut events = Vec::new();
1✔
339
        loop {
340
            match parser1.next_event() {
13✔
341
                Ok(Event::EndDocument) => break,
1✔
342
                Ok(event) => events.push(format!("{:?}", event)),
12✔
343
                Err(e) => panic!("Nested containers failed: {:?}", e),
×
344
            }
345
        }
346

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

350
        // Test 2: Mixed types after numbers in array
351
        let json2 = br#"[123, "string", true, null, 456]"#;
1✔
352
        let reader2 = SliceReader::new(json2);
1✔
353
        let mut buffer2 = [0u8; 256];
1✔
354
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
355

356
        let mut number_count = 0;
1✔
357
        loop {
358
            match parser2.next_event() {
8✔
359
                Ok(Event::EndDocument) => break,
1✔
360
                Ok(Event::Number(_)) => number_count += 1,
2✔
361
                Ok(_) => {}
5✔
362
                Err(e) => panic!("Mixed types failed: {:?}", e),
×
363
            }
364
        }
365
        assert_eq!(number_count, 2); // Should find both 123 and 456
1✔
366

367
        // Test 3: Empty containers
368
        let json3 = br#"[[], {}, [{}], {"empty": []}]"#;
1✔
369
        let reader3 = SliceReader::new(json3);
1✔
370
        let mut buffer3 = [0u8; 256];
1✔
371
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
372

373
        loop {
374
            match parser3.next_event() {
16✔
375
                Ok(Event::EndDocument) => break,
1✔
376
                Ok(_) => {}
15✔
377
                Err(e) => panic!("Empty containers failed: {:?}", e),
×
378
            }
379
        }
380

381
        // Test 4: Multiple consecutive numbers
382
        let json4 = br#"[1, 2, 3, 4, 5]"#;
1✔
383
        let reader4 = SliceReader::new(json4);
1✔
384
        let mut buffer4 = [0u8; 256];
1✔
385
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
1✔
386

387
        let mut consecutive_numbers = Vec::new();
1✔
388
        loop {
389
            match parser4.next_event() {
8✔
390
                Ok(Event::EndDocument) => break,
1✔
391
                Ok(Event::Number(n)) => consecutive_numbers.push(n.as_str().to_string()),
5✔
392
                Ok(_) => {}
2✔
393
                Err(e) => panic!("Consecutive numbers failed: {:?}", e),
×
394
            }
395
        }
396
        assert_eq!(consecutive_numbers, vec!["1", "2", "3", "4", "5"]);
1✔
397
    }
1✔
398

399
    #[test]
400
    fn test_error_recovery_with_pending_state() {
1✔
401
        // Test error handling - this should fail gracefully without hanging onto pending state
402
        let invalid_json = br#"{"key": 123,"#; // Missing closing brace
1✔
403
        let reader = SliceReader::new(invalid_json);
1✔
404
        let mut buffer = [0u8; 256];
1✔
405
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
406

407
        // Parse until we hit an error or EOF
408
        loop {
409
            match parser.next_event() {
4✔
410
                Ok(Event::EndDocument) => break, // EOF reached
×
411
                Ok(_) => {}
3✔
412
                Err(_) => break, // Error occurred - this is expected
1✔
413
            }
414
        }
415

416
        // The important thing is that we don't panic or hang
417
        // The specific error behavior may vary
418
    }
1✔
419

420
    #[test]
421
    fn test_multiple_rapid_container_ends() {
1✔
422
        // Test deeply nested structures that end with numbers
423
        // This tests whether we can handle multiple rapid container ends correctly
424

425
        // Test 1: Deeply nested arrays ending with number
426
        let json1 = br#"[[[123]]]"#;
1✔
427
        let reader1 = SliceReader::new(json1);
1✔
428
        let mut buffer1 = [0u8; 256];
1✔
429
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
430

431
        let mut events1 = Vec::new();
1✔
432
        loop {
433
            match parser1.next_event() {
8✔
434
                Ok(Event::EndDocument) => break,
1✔
435
                Ok(event) => events1.push(format!("{:?}", event)),
7✔
436
                Err(e) => panic!("Deeply nested arrays failed: {:?}", e),
×
437
            }
438
        }
439

440
        // Should have: StartArray, StartArray, StartArray, Number(123), EndArray, EndArray, EndArray
441
        assert_eq!(events1.len(), 7);
1✔
442
        assert!(events1[3].contains("Number"));
1✔
443
        assert_eq!(&events1[4], "EndArray");
1✔
444
        assert_eq!(&events1[5], "EndArray");
1✔
445
        assert_eq!(&events1[6], "EndArray");
1✔
446

447
        // Test 2: Mixed nested containers ending with number
448
        let json2 = br#"{"a": [{"b": 456}]}"#;
1✔
449
        let reader2 = SliceReader::new(json2);
1✔
450
        let mut buffer2 = [0u8; 256];
1✔
451
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
452

453
        let mut events2 = Vec::new();
1✔
454
        loop {
455
            match parser2.next_event() {
10✔
456
                Ok(Event::EndDocument) => break,
1✔
457
                Ok(event) => events2.push(format!("{:?}", event)),
9✔
458
                Err(e) => panic!("Mixed nested containers failed: {:?}", e),
×
459
            }
460
        }
461

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

465
        // Test 3: Multiple numbers at different nesting levels
466
        let json3 = br#"[123, [456, [789]]]"#;
1✔
467
        let reader3 = SliceReader::new(json3);
1✔
468
        let mut buffer3 = [0u8; 256];
1✔
469
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
470

471
        let mut number_count = 0;
1✔
472
        let mut events3 = Vec::new();
1✔
473
        loop {
474
            match parser3.next_event() {
10✔
475
                Ok(Event::EndDocument) => break,
1✔
476
                Ok(Event::Number(n)) => {
3✔
477
                    number_count += 1;
3✔
478
                    events3.push(format!("Number({})", n.as_str()));
3✔
479
                }
3✔
480
                Ok(event) => events3.push(format!("{:?}", event)),
6✔
481
                Err(e) => panic!("Multiple nested numbers failed: {:?}", e),
×
482
            }
483
        }
484

485
        assert_eq!(number_count, 3); // Should find all three numbers: 123, 456, 789
1✔
486
    }
1✔
487

488
    #[test]
489
    fn test_pending_flag_priority() {
1✔
490
        // Defensive test: ensure that if both pending flags were somehow set,
491
        // we handle it gracefully (this shouldn't happen in normal operation)
492

493
        let json = br#"[{"key": 123}]"#;
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
        // Parse normally - this should work fine and never set both flags
499
        let mut events = Vec::new();
1✔
500
        loop {
501
            match parser.next_event() {
7✔
502
                Ok(Event::EndDocument) => break,
1✔
503
                Ok(event) => events.push(format!("{:?}", event)),
6✔
504
                Err(e) => panic!("Flag priority test failed: {:?}", e),
×
505
            }
506
        }
507

508
        // Should successfully parse: StartArray, StartObject, Key, Number, EndObject, EndArray
509
        assert_eq!(events.len(), 6);
1✔
510
        assert!(events[3].contains("Number"));
1✔
511
        assert_eq!(&events[4], "EndObject");
1✔
512
        assert_eq!(&events[5], "EndArray");
1✔
513
    }
1✔
514

515
    #[test]
516
    fn test_direct_parser_array_of_strings() {
1✔
517
        let json = b"[\"first\", \"second\"]";
1✔
518
        let reader = SliceReader::new(json);
1✔
519
        let mut buffer = [0u8; 256];
1✔
520
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
521

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

524
        if let Event::String(s1) = parser.next_event().unwrap() {
1✔
525
            assert_eq!(s1.as_str(), "first");
1✔
526
        } else {
527
            panic!("Expected String event");
×
528
        }
529

530
        if let Event::String(s2) = parser.next_event().unwrap() {
1✔
531
            assert_eq!(s2.as_str(), "second");
1✔
532
        } else {
533
            panic!("Expected String event");
×
534
        }
535

536
        assert!(matches!(parser.next_event().unwrap(), Event::EndArray));
1✔
537
    }
1✔
538

539
    #[test]
540
    fn test_direct_parser_object_with_keys() {
1✔
541
        let json = b"{\"name\": \"value\", \"count\": \"42\"}";
1✔
542
        let reader = SliceReader::new(json);
1✔
543
        let mut buffer = [0u8; 256];
1✔
544
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
545

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

548
        // First key-value pair
549
        if let Event::Key(key1) = parser.next_event().unwrap() {
1✔
550
            assert_eq!(key1.as_str(), "name");
1✔
551
        } else {
552
            panic!("Expected Key event");
×
553
        }
554

555
        if let Event::String(val1) = parser.next_event().unwrap() {
1✔
556
            assert_eq!(val1.as_str(), "value");
1✔
557
        } else {
558
            panic!("Expected String event");
×
559
        }
560

561
        // Second key-value pair
562
        if let Event::Key(key2) = parser.next_event().unwrap() {
1✔
563
            assert_eq!(key2.as_str(), "count");
1✔
564
        } else {
565
            panic!("Expected Key event");
×
566
        }
567

568
        if let Event::String(val2) = parser.next_event().unwrap() {
1✔
569
            assert_eq!(val2.as_str(), "42");
1✔
570
        } else {
571
            panic!("Expected String event");
×
572
        }
573

574
        assert!(matches!(parser.next_event().unwrap(), Event::EndObject));
1✔
575
    }
1✔
576

577
    #[test]
578
    fn test_direct_parser_multiple_escapes() {
1✔
579
        let json = b"\"line1\\nline2\\ttab\\\"quote\"";
1✔
580
        let reader = SliceReader::new(json);
1✔
581
        let mut buffer = [0u8; 256];
1✔
582
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
583

584
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
585
            let content = json_string.as_str();
1✔
586
            // Check that escape sequences were properly processed
587
            let has_newline = content.contains('\n');
1✔
588
            let has_tab = content.contains('\t');
1✔
589
            let has_quote = content.contains('"');
1✔
590

591
            // These should be real control characters, not literal \n \t \"
592
            assert!(has_newline, "Should contain actual newline character");
1✔
593
            assert!(has_tab, "Should contain actual tab character");
1✔
594
            assert!(has_quote, "Should contain actual quote character");
1✔
595
        } else {
596
            panic!("Expected String event");
×
597
        }
598
    }
1✔
599

600
    #[test]
601
    fn test_direct_parser_unicode_escape() {
1✔
602
        let json = b"\"Hello \\u0041\\u03B1\""; // Hello A(alpha)
1✔
603
        let reader = SliceReader::new(json);
1✔
604
        let mut buffer = [0u8; 256];
1✔
605
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
606

607
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
608
            let content = json_string.as_str();
1✔
609
            // Should be "Hello A⍺" (with actual A and alpha characters)
610
            assert!(content.contains('A'));
1✔
611
            // Note: This test will initially fail until we implement Unicode escapes
612
        } else {
613
            panic!("Expected String event");
×
614
        }
615
    }
1✔
616

617
    #[test]
618
    fn test_direct_parser_boolean_true() {
1✔
619
        let json = b"true";
1✔
620
        let reader = SliceReader::new(json);
1✔
621
        let mut buffer = [0u8; 256];
1✔
622
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
623

624
        let event = parser.next_event().unwrap();
1✔
625
        assert_eq!(event, Event::Bool(true));
1✔
626

627
        let event = parser.next_event().unwrap();
1✔
628
        assert_eq!(event, Event::EndDocument);
1✔
629
    }
1✔
630

631
    #[test]
632
    fn test_direct_parser_boolean_false() {
1✔
633
        let json = b"false";
1✔
634
        let reader = SliceReader::new(json);
1✔
635
        let mut buffer = [0u8; 256];
1✔
636
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
637

638
        let event = parser.next_event().unwrap();
1✔
639
        assert_eq!(event, Event::Bool(false));
1✔
640

641
        let event = parser.next_event().unwrap();
1✔
642
        assert_eq!(event, Event::EndDocument);
1✔
643
    }
1✔
644

645
    #[test]
646
    fn test_direct_parser_null() {
1✔
647
        let json = b"null";
1✔
648
        let reader = SliceReader::new(json);
1✔
649
        let mut buffer = [0u8; 256];
1✔
650
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
651

652
        let event = parser.next_event().unwrap();
1✔
653
        assert_eq!(event, Event::Null);
1✔
654

655
        let event = parser.next_event().unwrap();
1✔
656
        assert_eq!(event, Event::EndDocument);
1✔
657
    }
1✔
658

659
    #[test]
660
    fn test_direct_parser_booleans_in_array() {
1✔
661
        let json = b"[true, false, null]";
1✔
662
        let reader = SliceReader::new(json);
1✔
663
        let mut buffer = [0u8; 256];
1✔
664
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
665

666
        assert_eq!(parser.next_event().unwrap(), Event::StartArray);
1✔
667
        assert_eq!(parser.next_event().unwrap(), Event::Bool(true));
1✔
668
        assert_eq!(parser.next_event().unwrap(), Event::Bool(false));
1✔
669
        assert_eq!(parser.next_event().unwrap(), Event::Null);
1✔
670
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1✔
671
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
672
    }
1✔
673

674
    #[test]
675
    fn test_direct_parser_number_simple() {
1✔
676
        let json = b"42";
1✔
677
        let reader = SliceReader::new(json);
1✔
678
        let mut buffer = [0u8; 256];
1✔
679
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
680

681
        let event = parser.next_event().unwrap();
1✔
682
        if let Event::Number(json_number) = event {
1✔
683
            assert_eq!(json_number.as_str(), "42");
1✔
684
        } else {
685
            panic!("Expected Number event, got: {:?}", event);
×
686
        }
687

688
        let event = parser.next_event().unwrap();
1✔
689
        assert_eq!(event, Event::EndDocument);
1✔
690
    }
1✔
691

692
    #[test]
693
    fn test_direct_parser_number_negative() {
1✔
694
        let json = b"-123";
1✔
695
        let reader = SliceReader::new(json);
1✔
696
        let mut buffer = [0u8; 256];
1✔
697
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
698

699
        let event = parser.next_event().unwrap();
1✔
700
        if let Event::Number(json_number) = event {
1✔
701
            assert_eq!(json_number.as_str(), "-123");
1✔
702
        } else {
703
            panic!("Expected Number event, got: {:?}", event);
×
704
        }
705

706
        let event = parser.next_event().unwrap();
1✔
707
        assert_eq!(event, Event::EndDocument);
1✔
708
    }
1✔
709

710
    #[test]
711
    fn test_direct_parser_number_float() {
1✔
712
        let json = b"3.14159";
1✔
713
        let reader = SliceReader::new(json);
1✔
714
        let mut buffer = [0u8; 256];
1✔
715
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
716

717
        #[cfg(feature = "float-error")]
718
        {
719
            // float-error configuration should return an error for float values
720
            let result = parser.next_event();
721
            assert!(
722
                result.is_err(),
723
                "Expected error for float with float-error configuration"
724
            );
725
            return;
726
        }
727

728
        #[cfg(not(feature = "float-error"))]
729
        {
730
            let event = parser.next_event().unwrap();
1✔
731
            if let Event::Number(json_number) = event {
1✔
732
                assert_eq!(json_number.as_str(), "3.14159");
1✔
733
            } else {
734
                panic!("Expected Number event, got: {:?}", event);
×
735
            }
736

737
            let event = parser.next_event().unwrap();
1✔
738
            assert_eq!(event, Event::EndDocument);
1✔
739
        }
740
    }
1✔
741

742
    #[test]
743
    fn test_direct_parser_numbers_in_array() {
1✔
744
        #[cfg(feature = "float-error")]
745
        let json = b"[42, -7]"; // No floats for float-error config
746
        #[cfg(not(feature = "float-error"))]
747
        let json = b"[42, -7, 3.14]"; // Include float for other configs
1✔
748

749
        let reader = SliceReader::new(json);
1✔
750
        let mut buffer = [0u8; 256];
1✔
751
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
752

753
        assert_eq!(parser.next_event().unwrap(), Event::StartArray);
1✔
754

755
        let event = parser.next_event().unwrap();
1✔
756
        if let Event::Number(json_number) = event {
1✔
757
            assert_eq!(json_number.as_str(), "42");
1✔
758
        } else {
759
            panic!("Expected Number event, got: {:?}", event);
×
760
        }
761

762
        let event = parser.next_event().unwrap();
1✔
763
        if let Event::Number(json_number) = event {
1✔
764
            assert_eq!(json_number.as_str(), "-7");
1✔
765
        } else {
766
            panic!("Expected Number event, got: {:?}", event);
×
767
        }
768

769
        #[cfg(not(feature = "float-error"))]
770
        {
771
            let event = parser.next_event().unwrap();
1✔
772
            if let Event::Number(json_number) = event {
1✔
773
                assert_eq!(json_number.as_str(), "3.14");
1✔
774
            } else {
775
                panic!("Expected Number event, got: {:?}", event);
×
776
            }
777
        }
778

779
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1✔
780
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
781
    }
1✔
782

783
    #[test]
784
    fn test_direct_parser_numbers_in_object() {
1✔
785
        #[cfg(feature = "float-error")]
786
        let json = b"{\"count\": 42, \"score\": -7}"; // No floats for float-error config
787
        #[cfg(not(feature = "float-error"))]
788
        let json = b"{\"count\": 42, \"score\": -7.5}"; // Include float for other configs
1✔
789

790
        let reader = SliceReader::new(json);
1✔
791
        let mut buffer = [0u8; 256];
1✔
792
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
793

794
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
795

796
        // First key-value pair
797
        if let Event::Key(key1) = parser.next_event().unwrap() {
1✔
798
            assert_eq!(key1.as_str(), "count");
1✔
799
        } else {
800
            panic!("Expected Key event");
×
801
        }
802

803
        if let Event::Number(val1) = parser.next_event().unwrap() {
1✔
804
            assert_eq!(val1.as_str(), "42");
1✔
805
        } else {
806
            panic!("Expected Number event");
×
807
        }
808

809
        // Second key-value pair
810
        if let Event::Key(key2) = parser.next_event().unwrap() {
1✔
811
            assert_eq!(key2.as_str(), "score");
1✔
812
        } else {
813
            panic!("Expected Key event");
×
814
        }
815

816
        if let Event::Number(val2) = parser.next_event().unwrap() {
1✔
817
            #[cfg(feature = "float-error")]
818
            assert_eq!(val2.as_str(), "-7");
819
            #[cfg(not(feature = "float-error"))]
820
            assert_eq!(val2.as_str(), "-7.5");
1✔
821
        } else {
822
            panic!("Expected Number event");
×
823
        }
824

825
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
826
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
827
    }
1✔
828

829
    #[test]
830
    fn test_direct_parser_no_float_configuration() {
1✔
831
        // Test that StreamParser properly uses unified number parsing with no-float config
832
        let json = br#"{"integer": 42, "float": 3.14, "scientific": 1e3}"#;
1✔
833
        let reader = SliceReader::new(json);
1✔
834
        let mut buffer = [0u8; 256];
1✔
835
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
836

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

840
        // Integer key-value
841
        assert_eq!(
1✔
842
            parser.next_event().unwrap(),
1✔
843
            Event::Key(crate::String::Borrowed("integer"))
844
        );
845
        if let Event::Number(num) = parser.next_event().unwrap() {
1✔
846
            assert_eq!(num.as_str(), "42");
1✔
847
            match num.parsed() {
1✔
848
                crate::NumberResult::Integer(i) => assert_eq!(*i, 42),
1✔
849
                _ => panic!("Expected integer parsing"),
×
850
            }
851
        } else {
852
            panic!("Expected Number event");
×
853
        }
854

855
        // Float key-value - behavior varies by configuration
856
        assert_eq!(
1✔
857
            parser.next_event().unwrap(),
1✔
858
            Event::Key(crate::String::Borrowed("float"))
859
        );
860

861
        #[cfg(feature = "float-error")]
862
        {
863
            // float-error should return an error when encountering floats
864
            let result = parser.next_event();
865
            assert!(
866
                result.is_err(),
867
                "Expected error for float with float-error configuration"
868
            );
869
            // Test ends here for float-error - no more processing needed
870
        }
871

872
        #[cfg(not(feature = "float-error"))]
873
        {
874
            if let Event::Number(num) = parser.next_event().unwrap() {
1✔
875
                assert_eq!(num.as_str(), "3.14");
1✔
876
                // In no-float configuration, this should be FloatDisabled
877
                match num.parsed() {
1✔
878
                    #[cfg(not(feature = "float"))]
879
                    crate::NumberResult::FloatDisabled => {
880
                        // This is expected in no-float build
881
                    }
882
                    #[cfg(feature = "float")]
883
                    crate::NumberResult::Float(f) => {
1✔
884
                        // This is expected in float-enabled build
885
                        assert!((f - 3.14).abs() < 0.01);
1✔
886
                    }
887
                    #[cfg(feature = "float-skip")]
888
                    crate::NumberResult::FloatSkipped => {
889
                        // This is expected in float-skip build
890
                    }
891
                    #[cfg(feature = "float-truncate")]
892
                    crate::NumberResult::FloatTruncated(i) => {
893
                        // This is expected in float-truncate build (3.14 -> 3)
894
                        assert_eq!(*i, 3);
895
                    }
896
                    _ => panic!("Unexpected number parsing result for float"),
×
897
                }
898
            } else {
899
                panic!("Expected Number event");
×
900
            }
901

902
            // Scientific notation handling varies by float configuration
903
            assert_eq!(
1✔
904
                parser.next_event().unwrap(),
1✔
905
                Event::Key(crate::String::Borrowed("scientific"))
906
            );
907

908
            // float-truncate rejects scientific notation, so test should end early for that config
909
            #[cfg(feature = "float-truncate")]
910
            {
911
                // float-truncate rejects scientific notation since it would require float math
912
                let result = parser.next_event();
913
                assert!(
914
                    result.is_err(),
915
                    "Expected error for scientific notation with float-truncate"
916
                );
917
                // Test ends here for float-truncate - no more processing needed
918
            }
919

920
            #[cfg(not(feature = "float-truncate"))]
921
            {
922
                if let Event::Number(num) = parser.next_event().unwrap() {
1✔
923
                    assert_eq!(num.as_str(), "1e3");
1✔
924
                    match num.parsed() {
1✔
925
                        #[cfg(not(feature = "float"))]
926
                        crate::NumberResult::FloatDisabled => {
927
                            // This is expected in no-float build - raw string preserved for manual parsing
928
                        }
929
                        #[cfg(feature = "float-skip")]
930
                        crate::NumberResult::FloatSkipped => {
931
                            // This is expected in float-skip build
932
                        }
933
                        #[cfg(feature = "float")]
934
                        crate::NumberResult::Float(f) => {
1✔
935
                            // This is expected in float-enabled build
936
                            assert!((f - 1000.0).abs() < f64::EPSILON);
1✔
937
                        }
938
                        _ => panic!("Unexpected number parsing result for scientific notation"),
×
939
                    }
940
                } else {
941
                    panic!("Expected Number event");
×
942
                }
943

944
                assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
945
                assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
946
            }
947
        }
948
    }
1✔
949

950
    #[test]
951
    fn test_number_parsing_delimiter_exclusion() {
1✔
952
        // Test that numbers don't include trailing delimiters in various contexts
953

954
        // Test 1: Number followed by array end
955
        let json1 = b"[123]";
1✔
956
        let reader1 = SliceReader::new(json1);
1✔
957
        let mut buffer1 = [0u8; 256];
1✔
958
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
959

960
        assert!(matches!(parser1.next_event().unwrap(), Event::StartArray));
1✔
961
        if let Event::Number(num) = parser1.next_event().unwrap() {
1✔
962
            assert_eq!(
1✔
963
                num.as_str(),
1✔
964
                "123",
965
                "Number should not include trailing delimiter ']'"
×
966
            );
967
        } else {
968
            panic!("Expected Number event");
×
969
        }
970
        assert!(matches!(parser1.next_event().unwrap(), Event::EndArray));
1✔
971

972
        // Test 2: Number followed by object end
973
        let json2 = b"{\"key\":456}";
1✔
974
        let reader2 = SliceReader::new(json2);
1✔
975
        let mut buffer2 = [0u8; 256];
1✔
976
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
977

978
        assert!(matches!(parser2.next_event().unwrap(), Event::StartObject));
1✔
979
        assert!(matches!(parser2.next_event().unwrap(), Event::Key(_)));
1✔
980
        if let Event::Number(num) = parser2.next_event().unwrap() {
1✔
981
            assert_eq!(
1✔
982
                num.as_str(),
1✔
983
                "456",
984
                "Number should not include trailing delimiter '}}'"
×
985
            );
986
        } else {
987
            panic!("Expected Number event");
×
988
        }
989
        assert!(matches!(parser2.next_event().unwrap(), Event::EndObject));
1✔
990

991
        // Test 3: Number followed by comma in array
992
        let json3 = b"[789,10]";
1✔
993
        let reader3 = SliceReader::new(json3);
1✔
994
        let mut buffer3 = [0u8; 256];
1✔
995
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
996

997
        assert!(matches!(parser3.next_event().unwrap(), Event::StartArray));
1✔
998
        if let Event::Number(num1) = parser3.next_event().unwrap() {
1✔
999
            assert_eq!(
1✔
1000
                num1.as_str(),
1✔
1001
                "789",
1002
                "First number should not include trailing delimiter ','"
×
1003
            );
1004
        } else {
1005
            panic!("Expected first Number event");
×
1006
        }
1007
        if let Event::Number(num2) = parser3.next_event().unwrap() {
1✔
1008
            assert_eq!(
1✔
1009
                num2.as_str(),
1✔
1010
                "10",
1011
                "Second number should not include trailing delimiter ']'"
×
1012
            );
1013
        } else {
1014
            panic!("Expected second Number event");
×
1015
        }
1016
        assert!(matches!(parser3.next_event().unwrap(), Event::EndArray));
1✔
1017

1018
        // Test 4: Number followed by comma in object
1019
        let json4 = b"{\"a\":11,\"b\":22}";
1✔
1020
        let reader4 = SliceReader::new(json4);
1✔
1021
        let mut buffer4 = [0u8; 256];
1✔
1022
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
1✔
1023

1024
        assert!(matches!(parser4.next_event().unwrap(), Event::StartObject));
1✔
1025
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1✔
1026
        if let Event::Number(num1) = parser4.next_event().unwrap() {
1✔
1027
            assert_eq!(
1✔
1028
                num1.as_str(),
1✔
1029
                "11",
1030
                "First number should not include trailing delimiter ','"
×
1031
            );
1032
        } else {
1033
            panic!("Expected first Number event");
×
1034
        }
1035
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1✔
1036
        if let Event::Number(num2) = parser4.next_event().unwrap() {
1✔
1037
            assert_eq!(
1✔
1038
                num2.as_str(),
1✔
1039
                "22",
1040
                "Second number should not include trailing delimiter '}}'"
×
1041
            );
1042
        } else {
1043
            panic!("Expected second Number event");
×
1044
        }
1045
        assert!(matches!(parser4.next_event().unwrap(), Event::EndObject));
1✔
1046

1047
        // Test 5: Standalone number at end of document (should include full content)
1048
        let json5 = b"999";
1✔
1049
        let reader5 = SliceReader::new(json5);
1✔
1050
        let mut buffer5 = [0u8; 256];
1✔
1051
        let mut parser5 = TestStreamParser::new(reader5, &mut buffer5);
1✔
1052

1053
        if let Event::Number(num) = parser5.next_event().unwrap() {
1✔
1054
            assert_eq!(
1✔
1055
                num.as_str(),
1✔
1056
                "999",
1057
                "Standalone number should include full content"
×
1058
            );
1059
        } else {
1060
            panic!("Expected Number event");
×
1061
        }
1062
        assert!(matches!(parser5.next_event().unwrap(), Event::EndDocument));
1✔
1063

1064
        // Test 6: Negative numbers with delimiters
1065
        let json6 = b"[-42,33]";
1✔
1066
        let reader6 = SliceReader::new(json6);
1✔
1067
        let mut buffer6 = [0u8; 256];
1✔
1068
        let mut parser6 = TestStreamParser::new(reader6, &mut buffer6);
1✔
1069

1070
        assert!(matches!(parser6.next_event().unwrap(), Event::StartArray));
1✔
1071
        if let Event::Number(num1) = parser6.next_event().unwrap() {
1✔
1072
            assert_eq!(
1✔
1073
                num1.as_str(),
1✔
1074
                "-42",
1075
                "Negative number should not include trailing delimiter ','"
×
1076
            );
1077
        } else {
1078
            panic!("Expected first Number event");
×
1079
        }
1080
        if let Event::Number(num2) = parser6.next_event().unwrap() {
1✔
1081
            assert_eq!(
1✔
1082
                num2.as_str(),
1✔
1083
                "33",
1084
                "Second number should not include trailing delimiter ']'"
×
1085
            );
1086
        } else {
1087
            panic!("Expected second Number event");
×
1088
        }
1089
        assert!(matches!(parser6.next_event().unwrap(), Event::EndArray));
1✔
1090

1091
        // Test 7: Decimal numbers with delimiters (if float enabled)
1092
        #[cfg(not(feature = "float-error"))]
1093
        {
1094
            let json7 = b"[3.14,2.71]";
1✔
1095
            let reader7 = SliceReader::new(json7);
1✔
1096
            let mut buffer7 = [0u8; 256];
1✔
1097
            let mut parser7 = TestStreamParser::new(reader7, &mut buffer7);
1✔
1098

1099
            assert!(matches!(parser7.next_event().unwrap(), Event::StartArray));
1✔
1100
            if let Event::Number(num1) = parser7.next_event().unwrap() {
1✔
1101
                assert_eq!(
1✔
1102
                    num1.as_str(),
1✔
1103
                    "3.14",
1104
                    "Decimal number should not include trailing delimiter ','"
×
1105
                );
1106
            } else {
1107
                panic!("Expected first Number event");
×
1108
            }
1109
            if let Event::Number(num2) = parser7.next_event().unwrap() {
1✔
1110
                assert_eq!(
1✔
1111
                    num2.as_str(),
1✔
1112
                    "2.71",
1113
                    "Second decimal number should not include trailing delimiter ']'"
×
1114
                );
1115
            } else {
1116
                panic!("Expected second Number event");
×
1117
            }
1118
            assert!(matches!(parser7.next_event().unwrap(), Event::EndArray));
1✔
1119
        }
1120
    }
1✔
1121

1122
    #[test]
1123
    fn test_escape_buffer_functions() {
1✔
1124
        // Test the uncovered escape processing functions
1125
        let json_stream = br#"{"escaped": "test\nstring"}"#;
1✔
1126
        let mut buffer = [0u8; 1024];
1✔
1127
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1✔
1128

1129
        // These functions are private but we can test them through the public API
1130
        // The escape processing should trigger the uncovered functions
1131
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1132
        assert_eq!(
1✔
1133
            parser.next_event().unwrap(),
1✔
1134
            Event::Key(crate::String::Borrowed("escaped"))
1135
        );
1136

1137
        // This should trigger append_byte_to_escape_buffer and queue_unescaped_reset
1138
        if let Event::String(s) = parser.next_event().unwrap() {
1✔
1139
            assert_eq!(s.as_ref(), "test\nstring"); // Escape sequence should be processed
1✔
1140
        } else {
1141
            panic!("Expected String event with escape sequence");
×
1142
        }
1143

1144
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1145
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1146
    }
1✔
1147

1148
    #[test]
1149
    fn test_slice_reader_constructor() {
1✔
1150
        // Test the uncovered SliceReader::new function
1151
        let data = b"test data";
1✔
1152
        let reader = SliceReader::new(data);
1✔
1153
        assert_eq!(reader.data, data);
1✔
1154
        assert_eq!(reader.position, 0);
1✔
1155
    }
1✔
1156

1157
    #[test]
1158
    fn test_complex_escape_sequences() {
1✔
1159
        // Test more complex escape processing to cover the escape buffer functions
1160
        let json_stream = br#"{"multi": "line1\nline2\ttab\r\n"}"#;
1✔
1161
        let mut buffer = [0u8; 1024];
1✔
1162
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1✔
1163

1164
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1165
        assert_eq!(
1✔
1166
            parser.next_event().unwrap(),
1✔
1167
            Event::Key(crate::String::Borrowed("multi"))
1168
        );
1169

1170
        // This should exercise the escape buffer processing extensively
1171
        if let Event::String(s) = parser.next_event().unwrap() {
1✔
1172
            assert_eq!(s.as_ref(), "line1\nline2\ttab\r\n");
1✔
1173
        } else {
1174
            panic!("Expected String event");
×
1175
        }
1176

1177
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1178
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1179
    }
1✔
1180

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

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

1190
        // Array start
1191
        assert!(matches!(parser.next_event()?, Event::StartArray));
3✔
1192

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

1196
        // Array end
1197
        assert!(matches!(parser.next_event()?, Event::EndArray));
2✔
1198

1199
        // End document
1200
        assert!(matches!(parser.next_event()?, Event::EndDocument));
2✔
1201

1202
        Ok(())
2✔
1203
    }
3✔
1204

1205
    #[test]
1206
    fn test_minimal_buffer_simple_escape_1() {
1✔
1207
        // Buffer size 4 - clearly not enough
1208
        assert!(matches!(
1✔
1209
            test_simple_escape_with_buffer_size(4),
1✔
1210
            Err(crate::ParseError::ScratchBufferFull)
1211
        ));
1212
    }
1✔
1213

1214
    #[test]
1215
    fn test_minimal_buffer_simple_escape_2() {
1✔
1216
        // Buffer size 12 - test if larger buffer avoids compaction bugs
1217
        test_simple_escape_with_buffer_size(12)
1✔
1218
            .expect("12-byte buffer should be sufficient for simple escape");
1✔
1219
    }
1✔
1220

1221
    #[test]
1222
    fn test_minimal_buffer_simple_escape_3() {
1✔
1223
        // Buffer size 24 - known working boundary from stress tests
1224
        test_simple_escape_with_buffer_size(24).expect("24-byte buffer should definitely work");
1✔
1225
    }
1✔
1226

1227
    #[test]
1228
    fn test_surrogate_pair_buffer_boundary_cases() {
1✔
1229
        // Test 7: Surrogate pair split across very small buffer chunks
1230
        let input7 = r#"["\uD801\uDC37"]"#;
1✔
1231
        let mut buffer7 = [0u8; 16]; // Small buffer
1✔
1232
        let reader7 = crate::chunk_reader::ChunkReader::new(input7.as_bytes(), 3); // Tiny chunks
1✔
1233
        let mut parser7 = StreamParser::<_, DefaultConfig>::with_config(reader7, &mut buffer7);
1✔
1234
        assert_eq!(parser7.next_event(), Ok(Event::StartArray));
1✔
1235
        match parser7.next_event() {
1✔
1236
            Ok(Event::String(s)) => {
1✔
1237
                let content = match s {
1✔
1238
                    crate::String::Borrowed(c) => c,
×
1239
                    crate::String::Unescaped(c) => c,
1✔
1240
                };
1241
                assert_eq!(content, "𐐷");
1✔
1242
            }
1243
            other => panic!(
×
1244
                "Expected String with surrogate pair across buffer boundary, got: {:?}",
×
1245
                other
1246
            ),
1247
        }
1248

1249
        // Test 8: Surrogate pair with small buffer (still needs minimum space)
1250
        let input8 = r#"["\uD801\uDC37"]"#;
1✔
1251
        let mut buffer8 = [0u8; 32]; // Small but sufficient buffer
1✔
1252
        let reader8 = crate::chunk_reader::ChunkReader::new(input8.as_bytes(), 6); // Split at surrogate boundary
1✔
1253
        let mut parser8 = StreamParser::<_, DefaultConfig>::with_config(reader8, &mut buffer8);
1✔
1254
        assert_eq!(parser8.next_event(), Ok(Event::StartArray));
1✔
1255
        match parser8.next_event() {
1✔
1256
            Ok(Event::String(s)) => {
1✔
1257
                let content = match s {
1✔
1258
                    crate::String::Borrowed(c) => c,
×
1259
                    crate::String::Unescaped(c) => c,
1✔
1260
                };
1261
                assert_eq!(content, "𐐷");
1✔
1262
            }
1263
            other => panic!(
×
1264
                "Expected String with surrogate pair at small buffer, got: {:?}",
×
1265
                other
1266
            ),
1267
        }
1268
    }
1✔
1269
}
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