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

kaidokert / picojson-rs / 16097055412

06 Jul 2025 08:23AM UTC coverage: 93.392% (-1.2%) from 94.616%
16097055412

Pull #39

github

web-flow
Merge 563d94c53 into 19e3b1f38
Pull Request #39: Streambuffer debug

471 of 543 new or added lines in 5 files covered. (86.74%)

9 existing lines in 1 file now uncovered.

4127 of 4419 relevant lines covered (93.39%)

531.83 hits per line

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

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

3
use crate::escape_processor::{EscapeProcessor, UnicodeEscapeCollector};
4
use crate::shared::{ContentRange, Event, ParseError, ParserErrorHandler, ParserState};
5
use crate::stream_buffer::StreamBuffer;
6
use crate::{ujson, PullParser};
7
use ujson::{EventToken, Tokenizer};
8

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

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

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

26
/// Represents the processing state of the StreamParser
27
/// Enforces logical invariants: once Finished, no other processing states are possible
28
#[derive(Debug)]
29
enum ProcessingState {
30
    /// Normal active processing
31
    Active {
32
        unescaped_reset_queued: bool,
33
        in_escape_sequence: bool,
34
    },
35
    /// All input consumed, tokenizer finished
36
    Finished,
37
}
38

39
/// A pull parser that parses JSON from a stream.
40
///
41
/// Generic over BitStackConfig for configurable nesting depth.
42
/// It is designed to be used with the [Reader] trait, which is used to read data from a stream.
43
///
44
pub struct StreamParser<'b, R: Reader, C: BitStackConfig = DefaultConfig> {
45
    /// The tokenizer that processes JSON tokens
46
    tokenizer: Tokenizer<C::Bucket, C::Counter>,
47
    /// Parser state tracking
48
    parser_state: ParserState,
49
    /// Reader for streaming input
50
    reader: R,
51
    /// StreamBuffer for single-buffer input and escape processing
52
    stream_buffer: StreamBuffer<'b>,
53

54
    /// Processing state machine that enforces logical invariants
55
    processing_state: ProcessingState,
56

57
    /// Shared Unicode escape collector for \uXXXX sequences
58
    unicode_escape_collector: UnicodeEscapeCollector,
59
}
60

61
/// Methods for StreamParser using DefaultConfig
62
impl<'b, R: Reader> StreamParser<'b, R, DefaultConfig> {
63
    /// Create a new StreamParser with default configuration
64
    ///
65
    /// Uses the default BitStack configuration (u32 bucket, u8 counter)
66
    /// for most common use cases.
67
    pub fn new(reader: R, buffer: &'b mut [u8]) -> Self {
1,026✔
68
        Self::with_config(reader, buffer)
1,026✔
69
    }
1,026✔
70
}
71

72
/// Methods for StreamParser with custom BitStackConfig
73
impl<'b, R: Reader, C: BitStackConfig> StreamParser<'b, R, C> {
74
    /// Create a new StreamParser with custom configuration
75
    ///
76
    /// Use this when you need custom BitStack storage types for specific
77
    /// memory or nesting depth requirements.
78
    ///
79
    /// # Example
80
    /// ```
81
    /// use picojson::{StreamParser, BitStackStruct, ArrayBitStack};
82
    ///
83
    /// # // Example Reader implementation
84
    /// # struct JsonReader<'a> { data: &'a [u8], pos: usize }
85
    /// # impl<'a> JsonReader<'a> {
86
    /// #     fn new(data: &'a [u8]) -> Self { Self { data, pos: 0 } }
87
    /// # }
88
    /// # impl picojson::Reader for JsonReader<'_> {
89
    /// #     type Error = ();
90
    /// #     fn read(&mut self, buf: &mut [u8]) -> Result<usize, ()> {
91
    /// #         let remaining = &self.data[self.pos..];
92
    /// #         let to_copy = buf.len().min(remaining.len());
93
    /// #         buf[..to_copy].copy_from_slice(&remaining[..to_copy]);
94
    /// #         self.pos += to_copy;
95
    /// #         Ok(to_copy)
96
    /// #     }
97
    /// # }
98
    /// #
99
    /// # let json = b"{\"test\": 42}";
100
    /// let reader = JsonReader::new(json);
101
    /// let mut buffer = [0u8; 256];
102
    ///
103
    /// // Custom configuration: u64 bucket + u16 counter for deeper nesting
104
    /// let mut parser = StreamParser::<_, BitStackStruct<u64, u16>>::with_config(reader, &mut buffer);
105
    /// ```
106
    pub fn with_config(reader: R, buffer: &'b mut [u8]) -> Self {
1,028✔
107
        Self {
1,028✔
108
            tokenizer: Tokenizer::new(),
1,028✔
109
            parser_state: ParserState::new(),
1,028✔
110
            reader,
1,028✔
111
            stream_buffer: StreamBuffer::new(buffer),
1,028✔
112

1,028✔
113
            // Initialize new state machine to Active with default values
1,028✔
114
            processing_state: ProcessingState::Active {
1,028✔
115
                unescaped_reset_queued: false,
1,028✔
116
                in_escape_sequence: false,
1,028✔
117
            },
1,028✔
118

1,028✔
119
            unicode_escape_collector: UnicodeEscapeCollector::new(),
1,028✔
120
        }
1,028✔
121
    }
1,028✔
122
}
123

124
/// Shared methods for StreamParser with any BitStackConfig
125
impl<R: Reader, C: BitStackConfig> StreamParser<'_, R, C> {
126
    /// Get the next JSON event from the stream
127
    fn next_event_impl(&mut self) -> Result<Event<'_, '_>, ParseError> {
4,760✔
128
        // Apply any queued unescaped content reset from previous call
129
        self.apply_unescaped_reset_if_queued();
4,760✔
130

131
        loop {
132
            // Pull events from tokenizer until we have some
133
            while !self.have_events() {
25,775✔
134
                // Only fill buffer when we actually need more data
135
                if self.stream_buffer.is_empty() {
18,356✔
136
                    self.fill_buffer_from_reader()?;
6,645✔
137
                }
11,711✔
138

139
                if self.stream_buffer.is_empty() {
17,827✔
140
                    // Handle end of data with tokenizer finish
141
                    if !matches!(self.processing_state, ProcessingState::Finished) {
468✔
142
                        self.processing_state = ProcessingState::Finished;
464✔
143

144
                        // Clear events and try to finish tokenizer
145
                        self.clear_events();
464✔
146
                        let mut callback = |event, _len| {
464✔
147
                            // Store events in the array, filling available slots
148
                            for evt in self.parser_state.evts.iter_mut() {
4✔
149
                                if evt.is_none() {
4✔
150
                                    *evt = Some(event);
4✔
151
                                    return;
4✔
152
                                }
×
153
                            }
154
                        };
4✔
155

156
                        if self.tokenizer.finish(&mut callback).is_err() {
464✔
157
                            return Err(ParseError::TokenizerError);
1✔
158
                        }
463✔
159
                    }
4✔
160

161
                    if !self.have_events() {
467✔
162
                        return Ok(Event::EndDocument);
463✔
163
                    }
4✔
164
                    // Continue to process any events generated by finish()
165
                } else {
166
                    // Get byte and advance
167
                    let byte = self.stream_buffer.current_byte()?;
17,359✔
168
                    self.stream_buffer.advance()?;
17,359✔
169

170
                    // Process byte through tokenizer
171
                    self.clear_events();
17,359✔
172
                    let mut callback = |event, _len| {
17,359✔
173
                        // Store events in the array, filling available slots
174
                        for evt in self.parser_state.evts.iter_mut() {
8,278✔
175
                            if evt.is_none() {
8,278✔
176
                                *evt = Some(event);
7,415✔
177
                                return;
7,415✔
178
                            }
863✔
179
                        }
180
                    };
7,415✔
181

182
                    if self.tokenizer.parse_chunk(&[byte], &mut callback).is_err() {
17,359✔
183
                        return Err(ParseError::TokenizerError);
×
184
                    }
17,359✔
185

186
                    // Special case processing removed - let all escape handling go through event system
187

188
                    // Handle byte accumulation if no event was generated
189
                    if !self.have_events() {
17,359✔
190
                        self.handle_byte_accumulation(byte)?;
10,807✔
191
                    }
6,552✔
192
                }
193
            }
194

195
            // Now we have events - process ONE event
196
            let taken_event = self.parser_state.evts.iter_mut().find_map(|e| e.take());
8,282✔
197

198
            if let Some(taken_event) = taken_event {
7,419✔
199
                // Process the event directly in the main loop
200
                match taken_event {
2,914✔
201
                    // Container events
202
                    ujson::Event::ObjectStart => return Ok(Event::StartObject),
197✔
203
                    ujson::Event::ObjectEnd => return Ok(Event::EndObject),
166✔
204
                    ujson::Event::ArrayStart => return Ok(Event::StartArray),
1,602✔
205
                    ujson::Event::ArrayEnd => return Ok(Event::EndArray),
971✔
206

207
                    // Primitive values
208
                    ujson::Event::Begin(
209
                        EventToken::True | EventToken::False | EventToken::Null,
210
                    ) => {
10✔
211
                        // Continue processing
10✔
212
                    }
10✔
213
                    ujson::Event::End(EventToken::True) => return Ok(Event::Bool(true)),
4✔
214
                    ujson::Event::End(EventToken::False) => return Ok(Event::Bool(false)),
3✔
215
                    ujson::Event::End(EventToken::Null) => return Ok(Event::Null),
3✔
216

217
                    // String/Key events
218
                    ujson::Event::Begin(EventToken::Key) => {
270✔
219
                        // Update parser state to track key content position
270✔
220
                        let current_pos = self.stream_buffer.current_position();
270✔
221
                        let content_start = ContentRange::content_start_from_current(current_pos);
270✔
222
                        self.parser_state.state = crate::shared::State::Key(content_start);
270✔
223
                        // Continue processing
270✔
224
                    }
270✔
225
                    ujson::Event::End(EventToken::Key) => {
226
                        // Extract key content from parser state
227
                        return self.extract_key_from_state();
240✔
228
                    }
229

230
                    // String events - same pattern as Key
231
                    ujson::Event::Begin(EventToken::String) => {
661✔
232
                        // Update parser state to track string content position
661✔
233
                        let current_pos = self.stream_buffer.current_position();
661✔
234
                        let content_start = ContentRange::content_start_from_current(current_pos);
661✔
235
                        self.parser_state.state = crate::shared::State::String(content_start);
661✔
236
                        // Continue processing
661✔
237
                    }
661✔
238
                    ujson::Event::End(EventToken::String) => {
239
                        // Extract string content from parser state
240
                        return self.extract_string_from_state();
354✔
241
                    }
242

243
                    // Number events
244
                    ujson::Event::Begin(EventToken::Number) => {
419✔
245
                        // Update parser state to track number position
419✔
246
                        let current_pos = self.stream_buffer.current_position();
419✔
247
                        let number_start = ContentRange::number_start_from_current(current_pos);
419✔
248
                        self.parser_state.state = crate::shared::State::Number(number_start);
419✔
249
                        // Continue processing
419✔
250
                    }
419✔
NEW
251
                    ujson::Event::Begin(EventToken::NumberAndArray) => {
×
NEW
252
                        // Update parser state to track number position
×
NEW
253
                        let current_pos = self.stream_buffer.current_position();
×
NEW
254
                        let number_start = ContentRange::number_start_from_current(current_pos);
×
NEW
255
                        self.parser_state.state = crate::shared::State::Number(number_start);
×
NEW
256
                        // Continue processing
×
NEW
257
                    }
×
NEW
258
                    ujson::Event::Begin(EventToken::NumberAndObject) => {
×
UNCOV
259
                        // Update parser state to track number position
×
UNCOV
260
                        let current_pos = self.stream_buffer.current_position();
×
UNCOV
261
                        let number_start = ContentRange::number_start_from_current(current_pos);
×
UNCOV
262
                        self.parser_state.state = crate::shared::State::Number(number_start);
×
UNCOV
263
                        // Continue processing
×
UNCOV
264
                    }
×
265
                    ujson::Event::End(EventToken::Number) => {
266
                        // Extract number content from parser state (standalone number)
267
                        return self.extract_number_from_state();
21✔
268
                    }
269
                    ujson::Event::End(EventToken::NumberAndArray) => {
270
                        // Extract number content (came from container delimiter)
271
                        return self.extract_number_from_state_with_context(true);
127✔
272
                    }
273
                    ujson::Event::End(EventToken::NumberAndObject) => {
274
                        // Extract number content (came from container delimiter)
275
                        return self.extract_number_from_state_with_context(true);
79✔
276
                    }
277

278
                    // Escape sequence handling
279
                    ujson::Event::Begin(EventToken::EscapeSequence) => {
280
                        // Start of escape sequence - we'll handle escapes by unescaping to buffer
281
                        self.start_escape_processing()?;
798✔
282
                        // Continue processing
283
                    }
284
                    ujson::Event::End(
285
                        escape_token @ (EventToken::EscapeQuote
657✔
286
                        | EventToken::EscapeBackslash
287
                        | EventToken::EscapeSlash
288
                        | EventToken::EscapeBackspace
289
                        | EventToken::EscapeFormFeed
290
                        | EventToken::EscapeNewline
291
                        | EventToken::EscapeCarriageReturn
292
                        | EventToken::EscapeTab),
293
                    ) => {
294
                        // Handle simple escape sequences
295
                        self.handle_simple_escape(&escape_token)?;
657✔
296
                        // Continue processing
297
                    }
298
                    ujson::Event::Begin(EventToken::UnicodeEscape) => {
299
                        // Start Unicode escape collection - reset collector for new sequence
300
                        // Only handle if we're inside a string or key
301
                        match self.parser_state.state {
99✔
302
                            crate::shared::State::String(_) | crate::shared::State::Key(_) => {
99✔
303
                                self.unicode_escape_collector.reset();
99✔
304
                            }
99✔
305
                            _ => {}
×
306
                        }
307
                        // Continue processing
308
                    }
309
                    ujson::Event::End(EventToken::UnicodeEscape) => {
310
                        // Handle end of Unicode escape sequence (\\uXXXX)
311
                        match self.parser_state.state {
81✔
312
                            crate::shared::State::String(_) | crate::shared::State::Key(_) => {
313
                                self.process_unicode_escape_with_collector()?;
81✔
314
                            }
315
                            _ => {}
×
316
                        }
317
                        // Continue processing
318
                    }
319

320
                    // All other events - continue processing
321
                    _ => {
657✔
322
                        // Continue to next byte
657✔
323
                    }
657✔
324
                }
325
            }
×
326
            // If no event was processed, continue the outer loop to get more events
327
        }
328
    }
4,760✔
329

330
    /// Check if we have events waiting to be processed
331
    fn have_events(&self) -> bool {
43,601✔
332
        self.parser_state.evts.iter().any(|evt| evt.is_some())
74,090✔
333
    }
43,601✔
334

335
    /// Extract number from parser state without 'static lifetime cheating
336
    fn extract_number_from_state(&mut self) -> Result<Event<'_, '_>, ParseError> {
21✔
337
        self.extract_number_from_state_with_context(false)
21✔
338
    }
21✔
339

340
    /// Extract string after all buffer operations are complete
341
    fn extract_string_from_state(&mut self) -> Result<Event<'_, '_>, ParseError> {
354✔
342
        let crate::shared::State::String(start_pos) = self.parser_state.state else {
354✔
343
            return Err(ParserErrorHandler::state_mismatch("string", "extract"));
×
344
        };
345

346
        self.parser_state.state = crate::shared::State::None;
354✔
347

348
        if self.stream_buffer.has_unescaped_content() {
354✔
349
            self.create_unescaped_string()
152✔
350
        } else {
351
            self.create_borrowed_string(start_pos)
202✔
352
        }
353
    }
354✔
354

355
    /// Helper to create an unescaped string from StreamBuffer
356
    fn create_unescaped_string(&mut self) -> Result<Event<'_, '_>, ParseError> {
152✔
357
        self.queue_unescaped_reset();
152✔
358
        let unescaped_slice = self.stream_buffer.get_unescaped_slice()?;
152✔
359
        let str_content = crate::shared::from_utf8(unescaped_slice)?;
152✔
360
        Ok(Event::String(crate::String::Unescaped(str_content)))
152✔
361
    }
152✔
362

363
    /// Helper to create a borrowed string from StreamBuffer
364
    fn create_borrowed_string(
202✔
365
        &mut self,
202✔
366
        content_start: usize,
202✔
367
    ) -> Result<Event<'_, '_>, ParseError> {
202✔
368
        let current_pos = self.stream_buffer.current_position();
202✔
369
        let (content_start, content_end) =
202✔
370
            ContentRange::string_content_bounds_from_content_start(content_start, current_pos);
202✔
371

372
        let bytes = self
202✔
373
            .stream_buffer
202✔
374
            .get_string_slice(content_start, content_end)?;
202✔
375
        let str_content = crate::shared::from_utf8(bytes)?;
202✔
376
        Ok(Event::String(crate::String::Borrowed(str_content)))
202✔
377
    }
202✔
378

379
    /// Extract key after all buffer operations are complete
380
    fn extract_key_from_state(&mut self) -> Result<Event<'_, '_>, ParseError> {
240✔
381
        let crate::shared::State::Key(start_pos) = self.parser_state.state else {
240✔
382
            return Err(ParserErrorHandler::state_mismatch("key", "extract"));
×
383
        };
384

385
        self.parser_state.state = crate::shared::State::None;
240✔
386

387
        if self.stream_buffer.has_unescaped_content() {
240✔
388
            self.create_unescaped_key()
×
389
        } else {
390
            self.create_borrowed_key(start_pos)
240✔
391
        }
392
    }
240✔
393

394
    /// Helper to create an unescaped key from StreamBuffer
395
    fn create_unescaped_key(&mut self) -> Result<Event<'_, '_>, ParseError> {
×
396
        self.queue_unescaped_reset();
×
397
        let unescaped_slice = self.stream_buffer.get_unescaped_slice()?;
×
398
        let str_content = crate::shared::from_utf8(unescaped_slice)?;
×
399
        Ok(Event::Key(crate::String::Unescaped(str_content)))
×
400
    }
×
401

402
    /// Helper to create a borrowed key from StreamBuffer
403
    fn create_borrowed_key(&mut self, content_start: usize) -> Result<Event<'_, '_>, ParseError> {
240✔
404
        let current_pos = self.stream_buffer.current_position();
240✔
405
        let (content_start, content_end) =
240✔
406
            ContentRange::string_content_bounds_from_content_start(content_start, current_pos);
240✔
407

408
        let bytes = self
240✔
409
            .stream_buffer
240✔
410
            .get_string_slice(content_start, content_end)?;
240✔
411
        let str_content = crate::shared::from_utf8(bytes)?;
240✔
412
        Ok(Event::Key(crate::String::Borrowed(str_content)))
240✔
413
    }
240✔
414

415
    /// Extract number with delimiter context using unified parsing logic
416
    fn extract_number_from_state_with_context(
227✔
417
        &mut self,
227✔
418
        from_container_end: bool,
227✔
419
    ) -> Result<Event<'_, '_>, ParseError> {
227✔
420
        let crate::shared::State::Number(start_pos) = self.parser_state.state else {
227✔
421
            return Err(ParserErrorHandler::state_mismatch("number", "extract"));
×
422
        };
423

424
        self.parser_state.state = crate::shared::State::None;
227✔
425

426
        let number_token_start = start_pos;
227✔
427
        // Use unified number parsing logic
428
        crate::number_parser::parse_number_event(
227✔
429
            &self.stream_buffer,
227✔
430
            number_token_start,
227✔
431
            from_container_end,
227✔
432
        )
433
    }
227✔
434
    /// Clear event slots
435
    fn clear_events(&mut self) {
17,823✔
436
        self.parser_state.evts[0] = None;
17,823✔
437
        self.parser_state.evts[1] = None;
17,823✔
438
    }
17,823✔
439

440
    /// Fill buffer from reader
441
    fn fill_buffer_from_reader(&mut self) -> Result<(), ParseError> {
6,645✔
442
        if let Some(fill_slice) = self.stream_buffer.get_fill_slice() {
6,645✔
443
            let bytes_read = self
4,855✔
444
                .reader
4,855✔
445
                .read(fill_slice)
4,855✔
446
                .map_err(|_| ParseError::ReaderError)?;
4,855✔
447

448
            self.stream_buffer.mark_filled(bytes_read)?;
4,855✔
449
        } else {
450
            // Buffer is full - ALWAYS attempt compaction
451
            let compact_start_pos = match self.parser_state.state {
1,790✔
452
                crate::shared::State::Number(start_pos) => start_pos,
401✔
453
                crate::shared::State::Key(start_pos) => start_pos,
126✔
454
                crate::shared::State::String(start_pos) => start_pos,
702✔
455
                _ => {
456
                    let pos = self.stream_buffer.current_position();
561✔
457
                    pos
561✔
458
                }
459
            };
460

461
            let offset = self.stream_buffer.compact_from(compact_start_pos)?;
1,790✔
462

463
            if offset == 0 {
1,790✔
464
                // SOL: Buffer too small for current token
465
                return Err(ParseError::ScratchBufferFull);
529✔
466
            }
1,261✔
467

468
            // Update parser state positions
469
            self.update_positions_after_compaction(offset)?;
1,261✔
470

471
            // Try to fill again after compaction
472
            if let Some(fill_slice) = self.stream_buffer.get_fill_slice() {
1,261✔
473
                let bytes_read = self
1,261✔
474
                    .reader
1,261✔
475
                    .read(fill_slice)
1,261✔
476
                    .map_err(|_| ParseError::ReaderError)?;
1,261✔
477

478
                self.stream_buffer.mark_filled(bytes_read)?;
1,261✔
NEW
479
            }
×
480
        }
481
        Ok(())
6,116✔
482
    }
6,645✔
483

484
    /// Update parser state positions after buffer compaction
485
    fn update_positions_after_compaction(&mut self, offset: usize) -> Result<(), ParseError> {
1,261✔
486
        // Check for positions that would be discarded and need escape mode
487
        // CRITICAL: Position 0 is never discarded, regardless of offset
488
        let needs_escape_mode = match &self.parser_state.state {
1,261✔
489
            crate::shared::State::Key(pos) if *pos > 0 && *pos < offset => Some((*pos, true)), // true = is_key
96✔
490
            crate::shared::State::String(pos) if *pos > 0 && *pos < offset => Some((*pos, false)), // false = is_string
395✔
491
            crate::shared::State::Number(pos) if *pos > 0 && *pos < offset => {
209✔
NEW
492
                return Err(ParseError::ScratchBufferFull);
×
493
            }
494
            _ => None,
1,261✔
495
        };
496

497
        // Handle escape mode transition if needed
498
        if let Some((original_pos, is_key)) = needs_escape_mode {
1,261✔
NEW
499
            if is_key {
×
NEW
500
                self.switch_key_to_escape_mode(original_pos, offset)?;
×
501
            } else {
NEW
502
                self.switch_string_to_escape_mode(original_pos, offset)?;
×
503
            }
504
        }
1,261✔
505

506
        // Update positions
507
        match &mut self.parser_state.state {
1,261✔
508
            crate::shared::State::None => {
561✔
509
                // No position-based state to update
561✔
510
            }
561✔
511
            crate::shared::State::Key(pos) => {
96✔
512
                if *pos > 0 && *pos < offset {
96✔
NEW
513
                    *pos = 0; // Reset for escape mode
×
514
                } else if *pos >= offset {
96✔
515
                    *pos = pos.checked_sub(offset).unwrap_or(0); // Safe position adjustment
96✔
516
                }
96✔
517
                // else: *pos == 0 or *pos < offset with pos == 0, keep as-is
518
            }
519
            crate::shared::State::String(pos) => {
395✔
520
                if *pos > 0 && *pos < offset {
395✔
NEW
521
                    *pos = 0; // Reset for escape mode
×
522
                } else if *pos >= offset {
395✔
523
                    *pos = pos.checked_sub(offset).unwrap_or(0); // Safe position adjustment
395✔
524
                }
395✔
525
                // else: *pos == 0 or *pos < offset with pos == 0, keep as-is
526
            }
527
            crate::shared::State::Number(pos) => {
209✔
528
                if *pos >= offset {
209✔
529
                    *pos = pos.checked_sub(offset).unwrap_or(0); // Safe position adjustment
209✔
530
                } else {
209✔
NEW
531
                    *pos = 0; // Reset for discarded number start
×
NEW
532
                }
×
533
            }
534
        }
535

536
        Ok(())
1,261✔
537
    }
1,261✔
538

539
    /// Switch key processing to escape/copy mode when original position was discarded
NEW
540
    fn switch_key_to_escape_mode(
×
NEW
541
        &mut self,
×
NEW
542
        original_pos: usize,
×
NEW
543
        offset: usize,
×
NEW
544
    ) -> Result<(), ParseError> {
×
545
        // The key start position was in the discarded portion of the buffer
546

547
        // For keys, the original_pos now points to the content start (after opening quote)
548
        // If offset > original_pos, it means some actual content was discarded
549

550
        // Calculate how much actual key content was discarded
NEW
551
        let content_start = original_pos; // Key content starts at original_pos (now tracks content directly)
×
NEW
552
        let discarded_content = offset.saturating_sub(content_start);
×
553

NEW
554
        if discarded_content > 0 {
×
555
            // We lost some actual key content - this would require content recovery
556
            // For now, this is unsupported
NEW
557
            return Err(ParseError::ScratchBufferFull);
×
NEW
558
        }
×
559

560
        // No actual content was discarded, we can continue parsing
561
        // We can continue parsing the key from the current position
NEW
562
        Ok(())
×
NEW
563
    }
×
564

565
    /// Switch string processing to escape/copy mode when original position was discarded
NEW
566
    fn switch_string_to_escape_mode(
×
NEW
567
        &mut self,
×
NEW
568
        original_pos: usize,
×
NEW
569
        offset: usize,
×
NEW
570
    ) -> Result<(), ParseError> {
×
571
        // The string start position was in the discarded portion of the buffer
572

573
        // For strings, the original_pos now points to the content start (after opening quote)
574
        // If offset > original_pos, it means some actual content was discarded
575

576
        // Calculate how much actual string content was discarded
NEW
577
        let content_start = original_pos; // String content starts at original_pos (now tracks content directly)
×
NEW
578
        let discarded_content = offset.saturating_sub(content_start);
×
579

NEW
580
        if discarded_content > 0 {
×
581
            // We lost some actual string content - this would require content recovery
582
            // For now, this is unsupported
NEW
583
            return Err(ParseError::ScratchBufferFull);
×
UNCOV
584
        }
×
585

586
        // No actual content was discarded, we can continue parsing
587
        // We can continue parsing the string from the current position
UNCOV
588
        Ok(())
×
UNCOV
589
    }
×
590

591
    /// Handle byte accumulation for strings/keys and Unicode escape sequences
592
    fn handle_byte_accumulation(&mut self, byte: u8) -> Result<(), ParseError> {
10,807✔
593
        // Check if we're in a string or key state
594
        let in_string_mode = matches!(
10,807✔
595
            self.parser_state.state,
10,807✔
596
            crate::shared::State::String(_) | crate::shared::State::Key(_)
597
        );
598

599
        if in_string_mode {
10,807✔
600
            // Access escape state from enum
601
            let in_escape = if let ProcessingState::Active {
6,072✔
602
                in_escape_sequence, ..
6,072✔
603
            } = &self.processing_state
6,072✔
604
            {
605
                *in_escape_sequence
6,072✔
606
            } else {
607
                false
×
608
            };
609

610
            // Normal byte accumulation - all escape processing now goes through event system
611
            if !in_escape && self.stream_buffer.has_unescaped_content() {
6,072✔
612
                self.append_byte_to_escape_buffer(byte)?;
377✔
613
            }
5,695✔
614
        }
4,735✔
615

616
        Ok(())
10,807✔
617
    }
10,807✔
618

619
    /// Start escape processing using StreamBuffer
620
    fn start_escape_processing(&mut self) -> Result<(), ParseError> {
798✔
621
        // Update escape state in enum
622
        if let ProcessingState::Active {
623
            ref mut in_escape_sequence,
798✔
624
            ..
625
        } = self.processing_state
798✔
626
        {
798✔
627
            *in_escape_sequence = true;
798✔
628
        }
798✔
629

630
        // Initialize escape processing with StreamBuffer if not already started
631
        if !self.stream_buffer.has_unescaped_content() {
798✔
632
            if let crate::shared::State::String(start_pos) | crate::shared::State::Key(start_pos) =
266✔
633
                self.parser_state.state
266✔
634
            {
635
                let current_pos = self.stream_buffer.current_position();
266✔
636

637
                // With content tracking, start_pos is the content_start
638
                let content_start = start_pos;
266✔
639
                // Content to copy ends right before the escape character
640
                let content_end = ContentRange::end_position_excluding_delimiter(current_pos);
266✔
641

642
                // Estimate max length needed for unescaping (content so far + remaining buffer)
643
                let content_len = content_end.wrapping_sub(content_start);
266✔
644
                let max_escaped_len = self
266✔
645
                    .stream_buffer
266✔
646
                    .remaining_bytes()
266✔
647
                    .checked_add(content_len)
266✔
648
                    .ok_or(ParseError::NumericOverflow)?;
266✔
649

650
                // Start unescaping with StreamBuffer and copy existing content
651
                self.stream_buffer.start_unescaping_with_copy(
266✔
652
                    max_escaped_len,
266✔
653
                    content_start,
266✔
654
                    content_end,
266✔
655
                )?;
×
656
            }
×
657
        }
532✔
658

659
        Ok(())
798✔
660
    }
798✔
661

662
    /// Handle simple escape sequence using unified EscapeProcessor
663
    fn handle_simple_escape(&mut self, escape_token: &EventToken) -> Result<(), ParseError> {
657✔
664
        // Update escape state in enum
665
        if let ProcessingState::Active {
666
            ref mut in_escape_sequence,
657✔
667
            ..
668
        } = self.processing_state
657✔
669
        {
657✔
670
            *in_escape_sequence = false;
657✔
671
        }
657✔
672

673
        // Use unified escape token processing from EscapeProcessor
674
        if let Ok(unescaped_char) = EscapeProcessor::process_escape_token(escape_token) {
657✔
675
            self.append_byte_to_escape_buffer(unescaped_char)?;
657✔
676
        }
×
677

678
        Ok(())
657✔
679
    }
657✔
680

681
    /// Extracts hex digits from buffer and processes them through the collector
682
    fn process_unicode_escape_with_collector(&mut self) -> Result<(), ParseError> {
81✔
683
        // Update escape state in enum - Unicode escape processing is complete
684
        if let ProcessingState::Active {
685
            ref mut in_escape_sequence,
81✔
686
            ..
687
        } = self.processing_state
81✔
688
        {
81✔
689
            *in_escape_sequence = false;
81✔
690
        }
81✔
691

692
        let utf8_bytes_copy = {
81✔
693
            let current_pos = self.stream_buffer.current_position();
81✔
694
            let hex_slice_provider = |start, end| {
81✔
695
                self.stream_buffer
81✔
696
                    .get_string_slice(start, end)
81✔
697
                    .map_err(Into::into)
81✔
698
            };
81✔
699

700
            let mut utf8_buf = [0u8; 4];
81✔
701
            let (utf8_bytes, _escape_start_pos) =
81✔
702
                crate::escape_processor::process_unicode_escape_sequence(
81✔
703
                    current_pos,
81✔
704
                    &mut self.unicode_escape_collector,
81✔
705
                    hex_slice_provider,
81✔
706
                    &mut utf8_buf,
81✔
707
                )?;
×
708
            let mut copy = [0u8; 4];
81✔
709
            let len = utf8_bytes.len();
81✔
710
            if let Some(dest) = copy.get_mut(..len) {
81✔
711
                dest.copy_from_slice(utf8_bytes);
81✔
712
            }
81✔
713
            (copy, len)
81✔
714
        };
715

716
        if let Some(bytes_to_copy) = utf8_bytes_copy.0.get(..utf8_bytes_copy.1) {
81✔
717
            for &byte in bytes_to_copy {
321✔
718
                self.append_byte_to_escape_buffer(byte)?;
240✔
719
            }
720
        }
×
721
        Ok(())
81✔
722
    }
81✔
723

724
    /// Append a byte to the StreamBuffer's unescaped content
725
    fn append_byte_to_escape_buffer(&mut self, byte: u8) -> Result<(), ParseError> {
1,274✔
726
        self.stream_buffer
1,274✔
727
            .append_unescaped_byte(byte)
1,274✔
728
            .map_err(|e| e.into())
1,274✔
729
    }
1,274✔
730

731
    /// Queue a reset of unescaped content for the next next_event() call
732
    fn queue_unescaped_reset(&mut self) {
152✔
733
        // Set the reset flag in the Active state
734
        if let ProcessingState::Active {
735
            ref mut unescaped_reset_queued,
152✔
736
            ..
737
        } = self.processing_state
152✔
738
        {
152✔
739
            *unescaped_reset_queued = true;
152✔
740
        }
152✔
741
    }
152✔
742

743
    /// Apply queued unescaped content reset if flag is set
744
    fn apply_unescaped_reset_if_queued(&mut self) {
4,760✔
745
        // Check the enum field first
746
        let should_reset = if let ProcessingState::Active {
4,760✔
747
            ref mut unescaped_reset_queued,
4,756✔
748
            ..
749
        } = self.processing_state
4,760✔
750
        {
751
            let needs_reset = *unescaped_reset_queued;
4,756✔
752
            *unescaped_reset_queued = false; // Clear the flag
4,756✔
753
            needs_reset
4,756✔
754
        } else {
755
            false
4✔
756
        };
757

758
        if should_reset {
4,760✔
759
            self.stream_buffer.clear_unescaped();
125✔
760
        }
4,635✔
761
    }
4,760✔
762
}
763

764
impl<'b, R: Reader, C: BitStackConfig> PullParser for StreamParser<'b, R, C> {
765
    fn next_event(&mut self) -> Result<Event<'_, '_>, ParseError> {
4,760✔
766
        self.next_event_impl()
4,760✔
767
    }
4,760✔
768
}
769

770
#[cfg(test)]
771
mod tests {
772
    use super::*;
773

774
    /// Simple test reader that reads from a byte slice
775
    pub struct SliceReader<'a> {
776
        data: &'a [u8],
777
        position: usize,
778
    }
779

780
    impl<'a> SliceReader<'a> {
781
        pub fn new(data: &'a [u8]) -> Self {
39✔
782
            Self { data, position: 0 }
39✔
783
        }
39✔
784
    }
785

786
    impl Reader for SliceReader<'_> {
787
        type Error = ();
788

789
        fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
69✔
790
            let remaining = self.data.len().saturating_sub(self.position);
69✔
791
            if remaining == 0 {
69✔
792
                return Ok(0); // EOF
30✔
793
            }
39✔
794

795
            let to_copy = remaining.min(buf.len());
39✔
796
            let end_pos = self.position.saturating_add(to_copy);
39✔
797
            if let (Some(dest), Some(src)) = (
39✔
798
                buf.get_mut(..to_copy),
39✔
799
                self.data.get(self.position..end_pos),
39✔
800
            ) {
801
                dest.copy_from_slice(src);
39✔
802
                self.position = end_pos;
39✔
803
                Ok(to_copy)
39✔
804
            } else {
805
                Err(())
×
806
            }
807
        }
69✔
808
    }
809

810
    type TestStreamParser<'b> = StreamParser<'b, SliceReader<'static>>;
811

812
    #[test]
813
    fn test_direct_parser_simple_object() {
1✔
814
        let json = b"{}";
1✔
815
        let reader = SliceReader::new(json);
1✔
816
        let mut buffer = [0u8; 256];
1✔
817
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
818

819
        // Should get ObjectStart
820
        let event = parser.next_event().unwrap();
1✔
821
        assert!(matches!(event, Event::StartObject));
1✔
822

823
        // Should get ObjectEnd
824
        let event = parser.next_event().unwrap();
1✔
825
        assert!(matches!(event, Event::EndObject));
1✔
826

827
        // Should get EndDocument
828
        let event = parser.next_event().unwrap();
1✔
829
        assert!(matches!(event, Event::EndDocument));
1✔
830
    }
1✔
831

832
    #[test]
833
    fn test_direct_parser_simple_array() {
1✔
834
        let json = b"[]";
1✔
835
        let reader = SliceReader::new(json);
1✔
836
        let mut buffer = [0u8; 256];
1✔
837
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
838

839
        // Should get ArrayStart
840
        let event = parser.next_event().unwrap();
1✔
841
        assert!(matches!(event, Event::StartArray));
1✔
842

843
        // Should get ArrayEnd
844
        let event = parser.next_event().unwrap();
1✔
845
        assert!(matches!(event, Event::EndArray));
1✔
846

847
        // Should get EndDocument
848
        let event = parser.next_event().unwrap();
1✔
849
        assert!(matches!(event, Event::EndDocument));
1✔
850
    }
1✔
851

852
    #[test]
853
    fn test_direct_parser_simple_escape() {
1✔
854
        let json = b"\"hello\\nworld\"";
1✔
855
        let reader = SliceReader::new(json);
1✔
856
        let mut buffer = [0u8; 256];
1✔
857
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
858

859
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
860
            assert_eq!(json_string.as_str(), "hello\nworld");
1✔
861
        } else {
862
            panic!("Expected String event");
×
863
        }
864
    }
1✔
865

866
    #[test]
867
    fn test_pending_state_edge_cases() {
1✔
868
        // Test 1: Complex nested container endings
869
        let json1 = br#"{"a": {"b": [{"c": 123}]}}"#;
1✔
870
        let reader1 = SliceReader::new(json1);
1✔
871
        let mut buffer1 = [0u8; 256];
1✔
872
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
873

874
        let mut events = Vec::new();
1✔
875
        loop {
876
            match parser1.next_event() {
13✔
877
                Ok(Event::EndDocument) => break,
1✔
878
                Ok(event) => events.push(format!("{:?}", event)),
12✔
879
                Err(e) => panic!("Nested containers failed: {:?}", e),
×
880
            }
881
        }
882

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

886
        // Test 2: Mixed types after numbers in array
887
        let json2 = br#"[123, "string", true, null, 456]"#;
1✔
888
        let reader2 = SliceReader::new(json2);
1✔
889
        let mut buffer2 = [0u8; 256];
1✔
890
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
891

892
        let mut number_count = 0;
1✔
893
        loop {
894
            match parser2.next_event() {
8✔
895
                Ok(Event::EndDocument) => break,
1✔
896
                Ok(Event::Number(_)) => number_count += 1,
2✔
897
                Ok(_) => {}
5✔
898
                Err(e) => panic!("Mixed types failed: {:?}", e),
×
899
            }
900
        }
901
        assert_eq!(number_count, 2); // Should find both 123 and 456
1✔
902

903
        // Test 3: Empty containers
904
        let json3 = br#"[[], {}, [{}], {"empty": []}]"#;
1✔
905
        let reader3 = SliceReader::new(json3);
1✔
906
        let mut buffer3 = [0u8; 256];
1✔
907
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
908

909
        loop {
910
            match parser3.next_event() {
16✔
911
                Ok(Event::EndDocument) => break,
1✔
912
                Ok(_) => {}
15✔
913
                Err(e) => panic!("Empty containers failed: {:?}", e),
×
914
            }
915
        }
916

917
        // Test 4: Multiple consecutive numbers
918
        let json4 = br#"[1, 2, 3, 4, 5]"#;
1✔
919
        let reader4 = SliceReader::new(json4);
1✔
920
        let mut buffer4 = [0u8; 256];
1✔
921
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
1✔
922

923
        let mut consecutive_numbers = Vec::new();
1✔
924
        loop {
925
            match parser4.next_event() {
8✔
926
                Ok(Event::EndDocument) => break,
1✔
927
                Ok(Event::Number(n)) => consecutive_numbers.push(n.as_str().to_string()),
5✔
928
                Ok(_) => {}
2✔
929
                Err(e) => panic!("Consecutive numbers failed: {:?}", e),
×
930
            }
931
        }
932
        assert_eq!(consecutive_numbers, vec!["1", "2", "3", "4", "5"]);
1✔
933
    }
1✔
934

935
    #[test]
936
    fn test_error_recovery_with_pending_state() {
1✔
937
        // Test error handling - this should fail gracefully without hanging onto pending state
938
        let invalid_json = br#"{"key": 123,"#; // Missing closing brace
1✔
939
        let reader = SliceReader::new(invalid_json);
1✔
940
        let mut buffer = [0u8; 256];
1✔
941
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
942

943
        // Parse until we hit an error or EOF
944
        loop {
945
            match parser.next_event() {
4✔
946
                Ok(Event::EndDocument) => break, // EOF reached
×
947
                Ok(_) => {}
3✔
948
                Err(_) => break, // Error occurred - this is expected
1✔
949
            }
950
        }
951

952
        // The important thing is that we don't panic or hang
953
        // The specific error behavior may vary
954
    }
1✔
955

956
    #[test]
957
    fn test_multiple_rapid_container_ends() {
1✔
958
        // Test deeply nested structures that end with numbers
959
        // This tests whether we can handle multiple rapid container ends correctly
960

961
        // Test 1: Deeply nested arrays ending with number
962
        let json1 = br#"[[[123]]]"#;
1✔
963
        let reader1 = SliceReader::new(json1);
1✔
964
        let mut buffer1 = [0u8; 256];
1✔
965
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
966

967
        let mut events1 = Vec::new();
1✔
968
        loop {
969
            match parser1.next_event() {
8✔
970
                Ok(Event::EndDocument) => break,
1✔
971
                Ok(event) => events1.push(format!("{:?}", event)),
7✔
972
                Err(e) => panic!("Deeply nested arrays failed: {:?}", e),
×
973
            }
974
        }
975

976
        // Should have: StartArray, StartArray, StartArray, Number(123), EndArray, EndArray, EndArray
977
        assert_eq!(events1.len(), 7);
1✔
978
        assert!(events1[3].contains("Number"));
1✔
979
        assert_eq!(&events1[4], "EndArray");
1✔
980
        assert_eq!(&events1[5], "EndArray");
1✔
981
        assert_eq!(&events1[6], "EndArray");
1✔
982

983
        // Test 2: Mixed nested containers ending with number
984
        let json2 = br#"{"a": [{"b": 456}]}"#;
1✔
985
        let reader2 = SliceReader::new(json2);
1✔
986
        let mut buffer2 = [0u8; 256];
1✔
987
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
988

989
        let mut events2 = Vec::new();
1✔
990
        loop {
991
            match parser2.next_event() {
10✔
992
                Ok(Event::EndDocument) => break,
1✔
993
                Ok(event) => events2.push(format!("{:?}", event)),
9✔
994
                Err(e) => panic!("Mixed nested containers failed: {:?}", e),
×
995
            }
996
        }
997

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

1001
        // Test 3: Multiple numbers at different nesting levels
1002
        let json3 = br#"[123, [456, [789]]]"#;
1✔
1003
        let reader3 = SliceReader::new(json3);
1✔
1004
        let mut buffer3 = [0u8; 256];
1✔
1005
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
1006

1007
        let mut number_count = 0;
1✔
1008
        let mut events3 = Vec::new();
1✔
1009
        loop {
1010
            match parser3.next_event() {
10✔
1011
                Ok(Event::EndDocument) => break,
1✔
1012
                Ok(Event::Number(n)) => {
3✔
1013
                    number_count += 1;
3✔
1014
                    events3.push(format!("Number({})", n.as_str()));
3✔
1015
                }
3✔
1016
                Ok(event) => events3.push(format!("{:?}", event)),
6✔
1017
                Err(e) => panic!("Multiple nested numbers failed: {:?}", e),
×
1018
            }
1019
        }
1020

1021
        assert_eq!(number_count, 3); // Should find all three numbers: 123, 456, 789
1✔
1022
    }
1✔
1023

1024
    #[test]
1025
    fn test_pending_flag_priority() {
1✔
1026
        // Defensive test: ensure that if both pending flags were somehow set,
1027
        // we handle it gracefully (this shouldn't happen in normal operation)
1028

1029
        let json = br#"[{"key": 123}]"#;
1✔
1030
        let reader = SliceReader::new(json);
1✔
1031
        let mut buffer = [0u8; 256];
1✔
1032
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1033

1034
        // Parse normally - this should work fine and never set both flags
1035
        let mut events = Vec::new();
1✔
1036
        loop {
1037
            match parser.next_event() {
7✔
1038
                Ok(Event::EndDocument) => break,
1✔
1039
                Ok(event) => events.push(format!("{:?}", event)),
6✔
1040
                Err(e) => panic!("Flag priority test failed: {:?}", e),
×
1041
            }
1042
        }
1043

1044
        // Should successfully parse: StartArray, StartObject, Key, Number, EndObject, EndArray
1045
        assert_eq!(events.len(), 6);
1✔
1046
        assert!(events[3].contains("Number"));
1✔
1047
        assert_eq!(&events[4], "EndObject");
1✔
1048
        assert_eq!(&events[5], "EndArray");
1✔
1049
    }
1✔
1050

1051
    #[test]
1052
    fn test_direct_parser_array_of_strings() {
1✔
1053
        let json = b"[\"first\", \"second\"]";
1✔
1054
        let reader = SliceReader::new(json);
1✔
1055
        let mut buffer = [0u8; 256];
1✔
1056
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1057

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

1060
        if let Event::String(s1) = parser.next_event().unwrap() {
1✔
1061
            assert_eq!(s1.as_str(), "first");
1✔
1062
        } else {
1063
            panic!("Expected String event");
×
1064
        }
1065

1066
        if let Event::String(s2) = parser.next_event().unwrap() {
1✔
1067
            assert_eq!(s2.as_str(), "second");
1✔
1068
        } else {
1069
            panic!("Expected String event");
×
1070
        }
1071

1072
        assert!(matches!(parser.next_event().unwrap(), Event::EndArray));
1✔
1073
    }
1✔
1074

1075
    #[test]
1076
    fn test_direct_parser_object_with_keys() {
1✔
1077
        let json = b"{\"name\": \"value\", \"count\": \"42\"}";
1✔
1078
        let reader = SliceReader::new(json);
1✔
1079
        let mut buffer = [0u8; 256];
1✔
1080
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1081

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

1084
        // First key-value pair
1085
        if let Event::Key(key1) = parser.next_event().unwrap() {
1✔
1086
            assert_eq!(key1.as_str(), "name");
1✔
1087
        } else {
1088
            panic!("Expected Key event");
×
1089
        }
1090

1091
        if let Event::String(val1) = parser.next_event().unwrap() {
1✔
1092
            assert_eq!(val1.as_str(), "value");
1✔
1093
        } else {
1094
            panic!("Expected String event");
×
1095
        }
1096

1097
        // Second key-value pair
1098
        if let Event::Key(key2) = parser.next_event().unwrap() {
1✔
1099
            assert_eq!(key2.as_str(), "count");
1✔
1100
        } else {
1101
            panic!("Expected Key event");
×
1102
        }
1103

1104
        if let Event::String(val2) = parser.next_event().unwrap() {
1✔
1105
            assert_eq!(val2.as_str(), "42");
1✔
1106
        } else {
1107
            panic!("Expected String event");
×
1108
        }
1109

1110
        assert!(matches!(parser.next_event().unwrap(), Event::EndObject));
1✔
1111
    }
1✔
1112

1113
    #[test]
1114
    fn test_direct_parser_multiple_escapes() {
1✔
1115
        let json = b"\"line1\\nline2\\ttab\\\"quote\"";
1✔
1116
        let reader = SliceReader::new(json);
1✔
1117
        let mut buffer = [0u8; 256];
1✔
1118
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1119

1120
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
1121
            let content = json_string.as_str();
1✔
1122
            // Check that escape sequences were properly processed
1123
            let has_newline = content.contains('\n');
1✔
1124
            let has_tab = content.contains('\t');
1✔
1125
            let has_quote = content.contains('"');
1✔
1126

1127
            // These should be real control characters, not literal \n \t \"
1128
            assert!(has_newline, "Should contain actual newline character");
1✔
1129
            assert!(has_tab, "Should contain actual tab character");
1✔
1130
            assert!(has_quote, "Should contain actual quote character");
1✔
1131
        } else {
1132
            panic!("Expected String event");
×
1133
        }
1134
    }
1✔
1135

1136
    #[test]
1137
    fn test_direct_parser_unicode_escape() {
1✔
1138
        let json = b"\"Hello \\u0041\\u03B1\""; // Hello A(alpha)
1✔
1139
        let reader = SliceReader::new(json);
1✔
1140
        let mut buffer = [0u8; 256];
1✔
1141
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1142

1143
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
1144
            let content = json_string.as_str();
1✔
1145
            // Should be "Hello A⍺" (with actual A and alpha characters)
1146
            assert!(content.contains('A'));
1✔
1147
            // Note: This test will initially fail until we implement Unicode escapes
1148
        } else {
1149
            panic!("Expected String event");
×
1150
        }
1151
    }
1✔
1152

1153
    #[test]
1154
    fn test_direct_parser_boolean_true() {
1✔
1155
        let json = b"true";
1✔
1156
        let reader = SliceReader::new(json);
1✔
1157
        let mut buffer = [0u8; 256];
1✔
1158
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1159

1160
        let event = parser.next_event().unwrap();
1✔
1161
        assert_eq!(event, Event::Bool(true));
1✔
1162

1163
        let event = parser.next_event().unwrap();
1✔
1164
        assert_eq!(event, Event::EndDocument);
1✔
1165
    }
1✔
1166

1167
    #[test]
1168
    fn test_direct_parser_boolean_false() {
1✔
1169
        let json = b"false";
1✔
1170
        let reader = SliceReader::new(json);
1✔
1171
        let mut buffer = [0u8; 256];
1✔
1172
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1173

1174
        let event = parser.next_event().unwrap();
1✔
1175
        assert_eq!(event, Event::Bool(false));
1✔
1176

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

1181
    #[test]
1182
    fn test_direct_parser_null() {
1✔
1183
        let json = b"null";
1✔
1184
        let reader = SliceReader::new(json);
1✔
1185
        let mut buffer = [0u8; 256];
1✔
1186
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1187

1188
        let event = parser.next_event().unwrap();
1✔
1189
        assert_eq!(event, Event::Null);
1✔
1190

1191
        let event = parser.next_event().unwrap();
1✔
1192
        assert_eq!(event, Event::EndDocument);
1✔
1193
    }
1✔
1194

1195
    #[test]
1196
    fn test_direct_parser_booleans_in_array() {
1✔
1197
        let json = b"[true, false, null]";
1✔
1198
        let reader = SliceReader::new(json);
1✔
1199
        let mut buffer = [0u8; 256];
1✔
1200
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1201

1202
        assert_eq!(parser.next_event().unwrap(), Event::StartArray);
1✔
1203
        assert_eq!(parser.next_event().unwrap(), Event::Bool(true));
1✔
1204
        assert_eq!(parser.next_event().unwrap(), Event::Bool(false));
1✔
1205
        assert_eq!(parser.next_event().unwrap(), Event::Null);
1✔
1206
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1✔
1207
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1208
    }
1✔
1209

1210
    #[test]
1211
    fn test_direct_parser_number_simple() {
1✔
1212
        let json = b"42";
1✔
1213
        let reader = SliceReader::new(json);
1✔
1214
        let mut buffer = [0u8; 256];
1✔
1215
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1216

1217
        let event = parser.next_event().unwrap();
1✔
1218
        if let Event::Number(json_number) = event {
1✔
1219
            assert_eq!(json_number.as_str(), "42");
1✔
1220
        } else {
1221
            panic!("Expected Number event, got: {:?}", event);
×
1222
        }
1223

1224
        let event = parser.next_event().unwrap();
1✔
1225
        assert_eq!(event, Event::EndDocument);
1✔
1226
    }
1✔
1227

1228
    #[test]
1229
    fn test_direct_parser_number_negative() {
1✔
1230
        let json = b"-123";
1✔
1231
        let reader = SliceReader::new(json);
1✔
1232
        let mut buffer = [0u8; 256];
1✔
1233
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1234

1235
        let event = parser.next_event().unwrap();
1✔
1236
        if let Event::Number(json_number) = event {
1✔
1237
            assert_eq!(json_number.as_str(), "-123");
1✔
1238
        } else {
1239
            panic!("Expected Number event, got: {:?}", event);
×
1240
        }
1241

1242
        let event = parser.next_event().unwrap();
1✔
1243
        assert_eq!(event, Event::EndDocument);
1✔
1244
    }
1✔
1245

1246
    #[test]
1247
    fn test_direct_parser_number_float() {
1✔
1248
        let json = b"3.14159";
1✔
1249
        let reader = SliceReader::new(json);
1✔
1250
        let mut buffer = [0u8; 256];
1✔
1251
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1252

1253
        #[cfg(feature = "float-error")]
1254
        {
1255
            // float-error configuration should return an error for float values
1256
            let result = parser.next_event();
1257
            assert!(
1258
                result.is_err(),
1259
                "Expected error for float with float-error configuration"
1260
            );
1261
            return;
1262
        }
1263

1264
        #[cfg(not(feature = "float-error"))]
1265
        {
1266
            let event = parser.next_event().unwrap();
1✔
1267
            if let Event::Number(json_number) = event {
1✔
1268
                assert_eq!(json_number.as_str(), "3.14159");
1✔
1269
            } else {
1270
                panic!("Expected Number event, got: {:?}", event);
×
1271
            }
1272

1273
            let event = parser.next_event().unwrap();
1✔
1274
            assert_eq!(event, Event::EndDocument);
1✔
1275
        }
1276
    }
1✔
1277

1278
    #[test]
1279
    fn test_direct_parser_numbers_in_array() {
1✔
1280
        #[cfg(feature = "float-error")]
1281
        let json = b"[42, -7]"; // No floats for float-error config
1282
        #[cfg(not(feature = "float-error"))]
1283
        let json = b"[42, -7, 3.14]"; // Include float for other configs
1✔
1284

1285
        let reader = SliceReader::new(json);
1✔
1286
        let mut buffer = [0u8; 256];
1✔
1287
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1288

1289
        assert_eq!(parser.next_event().unwrap(), Event::StartArray);
1✔
1290

1291
        let event = parser.next_event().unwrap();
1✔
1292
        if let Event::Number(json_number) = event {
1✔
1293
            assert_eq!(json_number.as_str(), "42");
1✔
1294
        } else {
1295
            panic!("Expected Number event, got: {:?}", event);
×
1296
        }
1297

1298
        let event = parser.next_event().unwrap();
1✔
1299
        if let Event::Number(json_number) = event {
1✔
1300
            assert_eq!(json_number.as_str(), "-7");
1✔
1301
        } else {
1302
            panic!("Expected Number event, got: {:?}", event);
×
1303
        }
1304

1305
        #[cfg(not(feature = "float-error"))]
1306
        {
1307
            let event = parser.next_event().unwrap();
1✔
1308
            if let Event::Number(json_number) = event {
1✔
1309
                assert_eq!(json_number.as_str(), "3.14");
1✔
1310
            } else {
1311
                panic!("Expected Number event, got: {:?}", event);
×
1312
            }
1313
        }
1314

1315
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1✔
1316
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1317
    }
1✔
1318

1319
    #[test]
1320
    fn test_direct_parser_numbers_in_object() {
1✔
1321
        #[cfg(feature = "float-error")]
1322
        let json = b"{\"count\": 42, \"score\": -7}"; // No floats for float-error config
1323
        #[cfg(not(feature = "float-error"))]
1324
        let json = b"{\"count\": 42, \"score\": -7.5}"; // Include float for other configs
1✔
1325

1326
        let reader = SliceReader::new(json);
1✔
1327
        let mut buffer = [0u8; 256];
1✔
1328
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1329

1330
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1331

1332
        // First key-value pair
1333
        if let Event::Key(key1) = parser.next_event().unwrap() {
1✔
1334
            assert_eq!(key1.as_str(), "count");
1✔
1335
        } else {
1336
            panic!("Expected Key event");
×
1337
        }
1338

1339
        if let Event::Number(val1) = parser.next_event().unwrap() {
1✔
1340
            assert_eq!(val1.as_str(), "42");
1✔
1341
        } else {
1342
            panic!("Expected Number event");
×
1343
        }
1344

1345
        // Second key-value pair
1346
        if let Event::Key(key2) = parser.next_event().unwrap() {
1✔
1347
            assert_eq!(key2.as_str(), "score");
1✔
1348
        } else {
1349
            panic!("Expected Key event");
×
1350
        }
1351

1352
        if let Event::Number(val2) = parser.next_event().unwrap() {
1✔
1353
            #[cfg(feature = "float-error")]
1354
            assert_eq!(val2.as_str(), "-7");
1355
            #[cfg(not(feature = "float-error"))]
1356
            assert_eq!(val2.as_str(), "-7.5");
1✔
1357
        } else {
1358
            panic!("Expected Number event");
×
1359
        }
1360

1361
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1362
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1363
    }
1✔
1364

1365
    #[test]
1366
    fn test_direct_parser_no_float_configuration() {
1✔
1367
        // Test that StreamParser properly uses unified number parsing with no-float config
1368
        let json = br#"{"integer": 42, "float": 3.14, "scientific": 1e3}"#;
1✔
1369
        let reader = SliceReader::new(json);
1✔
1370
        let mut buffer = [0u8; 256];
1✔
1371
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1372

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

1376
        // Integer key-value
1377
        assert_eq!(
1✔
1378
            parser.next_event().unwrap(),
1✔
1379
            Event::Key(crate::String::Borrowed("integer"))
1380
        );
1381
        if let Event::Number(num) = parser.next_event().unwrap() {
1✔
1382
            assert_eq!(num.as_str(), "42");
1✔
1383
            match num.parsed() {
1✔
1384
                crate::NumberResult::Integer(i) => assert_eq!(*i, 42),
1✔
1385
                _ => panic!("Expected integer parsing"),
×
1386
            }
1387
        } else {
1388
            panic!("Expected Number event");
×
1389
        }
1390

1391
        // Float key-value - behavior varies by configuration
1392
        assert_eq!(
1✔
1393
            parser.next_event().unwrap(),
1✔
1394
            Event::Key(crate::String::Borrowed("float"))
1395
        );
1396

1397
        #[cfg(feature = "float-error")]
1398
        {
1399
            // float-error should return an error when encountering floats
1400
            let result = parser.next_event();
1401
            assert!(
1402
                result.is_err(),
1403
                "Expected error for float with float-error configuration"
1404
            );
1405
            // Test ends here for float-error - no more processing needed
1406
        }
1407

1408
        #[cfg(not(feature = "float-error"))]
1409
        {
1410
            if let Event::Number(num) = parser.next_event().unwrap() {
1✔
1411
                assert_eq!(num.as_str(), "3.14");
1✔
1412
                // In no-float configuration, this should be FloatDisabled
1413
                match num.parsed() {
1✔
1414
                    #[cfg(not(feature = "float"))]
1415
                    crate::NumberResult::FloatDisabled => {
1416
                        // This is expected in no-float build
1417
                    }
1418
                    #[cfg(feature = "float")]
1419
                    crate::NumberResult::Float(f) => {
1✔
1420
                        // This is expected in float-enabled build
1421
                        assert!((f - 3.14).abs() < 0.01);
1✔
1422
                    }
1423
                    #[cfg(feature = "float-skip")]
1424
                    crate::NumberResult::FloatSkipped => {
1425
                        // This is expected in float-skip build
1426
                    }
1427
                    #[cfg(feature = "float-truncate")]
1428
                    crate::NumberResult::FloatTruncated(i) => {
1429
                        // This is expected in float-truncate build (3.14 -> 3)
1430
                        assert_eq!(*i, 3);
1431
                    }
1432
                    _ => panic!("Unexpected number parsing result for float"),
×
1433
                }
1434
            } else {
1435
                panic!("Expected Number event");
×
1436
            }
1437

1438
            // Scientific notation handling varies by float configuration
1439
            assert_eq!(
1✔
1440
                parser.next_event().unwrap(),
1✔
1441
                Event::Key(crate::String::Borrowed("scientific"))
1442
            );
1443

1444
            // float-truncate rejects scientific notation, so test should end early for that config
1445
            #[cfg(feature = "float-truncate")]
1446
            {
1447
                // float-truncate rejects scientific notation since it would require float math
1448
                let result = parser.next_event();
1449
                assert!(
1450
                    result.is_err(),
1451
                    "Expected error for scientific notation with float-truncate"
1452
                );
1453
                // Test ends here for float-truncate - no more processing needed
1454
            }
1455

1456
            #[cfg(not(feature = "float-truncate"))]
1457
            {
1458
                if let Event::Number(num) = parser.next_event().unwrap() {
1✔
1459
                    assert_eq!(num.as_str(), "1e3");
1✔
1460
                    match num.parsed() {
1✔
1461
                        #[cfg(not(feature = "float"))]
1462
                        crate::NumberResult::FloatDisabled => {
1463
                            // This is expected in no-float build - raw string preserved for manual parsing
1464
                        }
1465
                        #[cfg(feature = "float-skip")]
1466
                        crate::NumberResult::FloatSkipped => {
1467
                            // This is expected in float-skip build
1468
                        }
1469
                        #[cfg(feature = "float")]
1470
                        crate::NumberResult::Float(f) => {
1✔
1471
                            // This is expected in float-enabled build
1472
                            assert!((f - 1000.0).abs() < f64::EPSILON);
1✔
1473
                        }
1474
                        _ => panic!("Unexpected number parsing result for scientific notation"),
×
1475
                    }
1476
                } else {
1477
                    panic!("Expected Number event");
×
1478
                }
1479

1480
                assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1481
                assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1482
            }
1483
        }
1484
    }
1✔
1485

1486
    #[test]
1487
    fn test_number_parsing_delimiter_exclusion() {
1✔
1488
        // Test that numbers don't include trailing delimiters in various contexts
1489

1490
        // Test 1: Number followed by array end
1491
        let json1 = b"[123]";
1✔
1492
        let reader1 = SliceReader::new(json1);
1✔
1493
        let mut buffer1 = [0u8; 256];
1✔
1494
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
1495

1496
        assert!(matches!(parser1.next_event().unwrap(), Event::StartArray));
1✔
1497
        if let Event::Number(num) = parser1.next_event().unwrap() {
1✔
1498
            assert_eq!(
1✔
1499
                num.as_str(),
1✔
1500
                "123",
1501
                "Number should not include trailing delimiter ']'"
×
1502
            );
1503
        } else {
1504
            panic!("Expected Number event");
×
1505
        }
1506
        assert!(matches!(parser1.next_event().unwrap(), Event::EndArray));
1✔
1507

1508
        // Test 2: Number followed by object end
1509
        let json2 = b"{\"key\":456}";
1✔
1510
        let reader2 = SliceReader::new(json2);
1✔
1511
        let mut buffer2 = [0u8; 256];
1✔
1512
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
1513

1514
        assert!(matches!(parser2.next_event().unwrap(), Event::StartObject));
1✔
1515
        assert!(matches!(parser2.next_event().unwrap(), Event::Key(_)));
1✔
1516
        if let Event::Number(num) = parser2.next_event().unwrap() {
1✔
1517
            assert_eq!(
1✔
1518
                num.as_str(),
1✔
1519
                "456",
1520
                "Number should not include trailing delimiter '}}'"
×
1521
            );
1522
        } else {
1523
            panic!("Expected Number event");
×
1524
        }
1525
        assert!(matches!(parser2.next_event().unwrap(), Event::EndObject));
1✔
1526

1527
        // Test 3: Number followed by comma in array
1528
        let json3 = b"[789,10]";
1✔
1529
        let reader3 = SliceReader::new(json3);
1✔
1530
        let mut buffer3 = [0u8; 256];
1✔
1531
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
1532

1533
        assert!(matches!(parser3.next_event().unwrap(), Event::StartArray));
1✔
1534
        if let Event::Number(num1) = parser3.next_event().unwrap() {
1✔
1535
            assert_eq!(
1✔
1536
                num1.as_str(),
1✔
1537
                "789",
1538
                "First number should not include trailing delimiter ','"
×
1539
            );
1540
        } else {
1541
            panic!("Expected first Number event");
×
1542
        }
1543
        if let Event::Number(num2) = parser3.next_event().unwrap() {
1✔
1544
            assert_eq!(
1✔
1545
                num2.as_str(),
1✔
1546
                "10",
1547
                "Second number should not include trailing delimiter ']'"
×
1548
            );
1549
        } else {
1550
            panic!("Expected second Number event");
×
1551
        }
1552
        assert!(matches!(parser3.next_event().unwrap(), Event::EndArray));
1✔
1553

1554
        // Test 4: Number followed by comma in object
1555
        let json4 = b"{\"a\":11,\"b\":22}";
1✔
1556
        let reader4 = SliceReader::new(json4);
1✔
1557
        let mut buffer4 = [0u8; 256];
1✔
1558
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
1✔
1559

1560
        assert!(matches!(parser4.next_event().unwrap(), Event::StartObject));
1✔
1561
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1✔
1562
        if let Event::Number(num1) = parser4.next_event().unwrap() {
1✔
1563
            assert_eq!(
1✔
1564
                num1.as_str(),
1✔
1565
                "11",
1566
                "First number should not include trailing delimiter ','"
×
1567
            );
1568
        } else {
1569
            panic!("Expected first Number event");
×
1570
        }
1571
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1✔
1572
        if let Event::Number(num2) = parser4.next_event().unwrap() {
1✔
1573
            assert_eq!(
1✔
1574
                num2.as_str(),
1✔
1575
                "22",
1576
                "Second number should not include trailing delimiter '}}'"
×
1577
            );
1578
        } else {
1579
            panic!("Expected second Number event");
×
1580
        }
1581
        assert!(matches!(parser4.next_event().unwrap(), Event::EndObject));
1✔
1582

1583
        // Test 5: Standalone number at end of document (should include full content)
1584
        let json5 = b"999";
1✔
1585
        let reader5 = SliceReader::new(json5);
1✔
1586
        let mut buffer5 = [0u8; 256];
1✔
1587
        let mut parser5 = TestStreamParser::new(reader5, &mut buffer5);
1✔
1588

1589
        if let Event::Number(num) = parser5.next_event().unwrap() {
1✔
1590
            assert_eq!(
1✔
1591
                num.as_str(),
1✔
1592
                "999",
1593
                "Standalone number should include full content"
×
1594
            );
1595
        } else {
1596
            panic!("Expected Number event");
×
1597
        }
1598
        assert!(matches!(parser5.next_event().unwrap(), Event::EndDocument));
1✔
1599

1600
        // Test 6: Negative numbers with delimiters
1601
        let json6 = b"[-42,33]";
1✔
1602
        let reader6 = SliceReader::new(json6);
1✔
1603
        let mut buffer6 = [0u8; 256];
1✔
1604
        let mut parser6 = TestStreamParser::new(reader6, &mut buffer6);
1✔
1605

1606
        assert!(matches!(parser6.next_event().unwrap(), Event::StartArray));
1✔
1607
        if let Event::Number(num1) = parser6.next_event().unwrap() {
1✔
1608
            assert_eq!(
1✔
1609
                num1.as_str(),
1✔
1610
                "-42",
1611
                "Negative number should not include trailing delimiter ','"
×
1612
            );
1613
        } else {
1614
            panic!("Expected first Number event");
×
1615
        }
1616
        if let Event::Number(num2) = parser6.next_event().unwrap() {
1✔
1617
            assert_eq!(
1✔
1618
                num2.as_str(),
1✔
1619
                "33",
1620
                "Second number should not include trailing delimiter ']'"
×
1621
            );
1622
        } else {
1623
            panic!("Expected second Number event");
×
1624
        }
1625
        assert!(matches!(parser6.next_event().unwrap(), Event::EndArray));
1✔
1626

1627
        // Test 7: Decimal numbers with delimiters (if float enabled)
1628
        #[cfg(not(feature = "float-error"))]
1629
        {
1630
            let json7 = b"[3.14,2.71]";
1✔
1631
            let reader7 = SliceReader::new(json7);
1✔
1632
            let mut buffer7 = [0u8; 256];
1✔
1633
            let mut parser7 = TestStreamParser::new(reader7, &mut buffer7);
1✔
1634

1635
            assert!(matches!(parser7.next_event().unwrap(), Event::StartArray));
1✔
1636
            if let Event::Number(num1) = parser7.next_event().unwrap() {
1✔
1637
                assert_eq!(
1✔
1638
                    num1.as_str(),
1✔
1639
                    "3.14",
1640
                    "Decimal number should not include trailing delimiter ','"
×
1641
                );
1642
            } else {
1643
                panic!("Expected first Number event");
×
1644
            }
1645
            if let Event::Number(num2) = parser7.next_event().unwrap() {
1✔
1646
                assert_eq!(
1✔
1647
                    num2.as_str(),
1✔
1648
                    "2.71",
1649
                    "Second decimal number should not include trailing delimiter ']'"
×
1650
                );
1651
            } else {
1652
                panic!("Expected second Number event");
×
1653
            }
1654
            assert!(matches!(parser7.next_event().unwrap(), Event::EndArray));
1✔
1655
        }
1656
    }
1✔
1657

1658
    #[test]
1659
    fn test_escape_buffer_functions() {
1✔
1660
        // Test the uncovered escape processing functions
1661
        let json_stream = br#"{"escaped": "test\nstring"}"#;
1✔
1662
        let mut buffer = [0u8; 1024];
1✔
1663
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1✔
1664

1665
        // These functions are private but we can test them through the public API
1666
        // The escape processing should trigger the uncovered functions
1667
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1668
        assert_eq!(
1✔
1669
            parser.next_event().unwrap(),
1✔
1670
            Event::Key(crate::String::Borrowed("escaped"))
1671
        );
1672

1673
        // This should trigger append_byte_to_escape_buffer and queue_unescaped_reset
1674
        if let Event::String(s) = parser.next_event().unwrap() {
1✔
1675
            assert_eq!(s.as_ref(), "test\nstring"); // Escape sequence should be processed
1✔
1676
        } else {
1677
            panic!("Expected String event with escape sequence");
×
1678
        }
1679

1680
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1681
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1682
    }
1✔
1683

1684
    #[test]
1685
    fn test_slice_reader_constructor() {
1✔
1686
        // Test the uncovered SliceReader::new function
1687
        let data = b"test data";
1✔
1688
        let reader = SliceReader::new(data);
1✔
1689
        assert_eq!(reader.data, data);
1✔
1690
        assert_eq!(reader.position, 0);
1✔
1691
    }
1✔
1692

1693
    #[test]
1694
    fn test_complex_escape_sequences() {
1✔
1695
        // Test more complex escape processing to cover the escape buffer functions
1696
        let json_stream = br#"{"multi": "line1\nline2\ttab\r\n"}"#;
1✔
1697
        let mut buffer = [0u8; 1024];
1✔
1698
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1✔
1699

1700
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1701
        assert_eq!(
1✔
1702
            parser.next_event().unwrap(),
1✔
1703
            Event::Key(crate::String::Borrowed("multi"))
1704
        );
1705

1706
        // This should exercise the escape buffer processing extensively
1707
        if let Event::String(s) = parser.next_event().unwrap() {
1✔
1708
            assert_eq!(s.as_ref(), "line1\nline2\ttab\r\n");
1✔
1709
        } else {
1710
            panic!("Expected String event");
×
1711
        }
1712

1713
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1714
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1715
    }
1✔
1716

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

1723
        println!("Testing escape sequence with buffer size: {}", buffer_size);
3✔
1724
        println!(
3✔
1725
            "JSON input: {:?}",
3✔
1726
            core::str::from_utf8(json_stream).unwrap()
3✔
1727
        );
1728
        let mut buffer = vec![0u8; buffer_size];
3✔
1729
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
3✔
1730

1731
        // Array start
1732
        match parser.next_event()? {
3✔
1733
            Event::StartArray => println!("  ✅ StartArray OK"),
3✔
NEW
1734
            other => panic!("Expected StartArray, got: {:?}", other),
×
1735
        }
1736

1737
        // String with escape
1738
        match parser.next_event()? {
3✔
1739
            Event::String(s) => {
2✔
1740
                println!("  ✅ String OK: '{}'", s.as_str());
2✔
1741
                assert_eq!(s.as_str(), "hello\\");
2✔
1742
            }
NEW
1743
            other => panic!("Expected String, got: {:?}", other),
×
1744
        }
1745

1746
        // Array end
1747
        match parser.next_event()? {
2✔
1748
            Event::EndArray => println!("  ✅ EndArray OK"),
2✔
NEW
1749
            other => panic!("Expected EndArray, got: {:?}", other),
×
1750
        }
1751

1752
        // End document
1753
        match parser.next_event()? {
2✔
1754
            Event::EndDocument => println!("  ✅ EndDocument OK"),
2✔
NEW
1755
            other => panic!("Expected EndDocument, got: {:?}", other),
×
1756
        }
1757

1758
        println!("  🎉 SUCCESS with buffer size: {}", buffer_size);
2✔
1759
        Ok(())
2✔
1760
    }
3✔
1761

1762
    #[test]
1763
    fn test_minimal_buffer_simple_escape_1() {
1✔
1764
        // Buffer size 4 - clearly not enough
1765
        match test_simple_escape_with_buffer_size(4) {
1✔
NEW
1766
            Ok(()) => panic!("Expected failure with 4-byte buffer, but succeeded!"),
×
1767
            Err(e) => println!("Expected failure with 4-byte buffer: {:?}", e),
1✔
1768
        }
1769
    }
1✔
1770

1771
    #[test]
1772
    fn test_minimal_buffer_simple_escape_2() {
1✔
1773
        // Buffer size 12 - test if larger buffer avoids compaction bugs
1774
        test_simple_escape_with_buffer_size(12)
1✔
1775
            .expect("12-byte buffer should be sufficient for simple escape");
1✔
1776
    }
1✔
1777

1778
    #[test]
1779
    fn test_minimal_buffer_simple_escape_3() {
1✔
1780
        // Buffer size 24 - known working boundary from stress tests
1781
        test_simple_escape_with_buffer_size(24).expect("24-byte buffer should definitely work");
1✔
1782
    }
1✔
1783
}
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