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

kaidokert / picojson-rs / 16095334159

06 Jul 2025 04:35AM UTC coverage: 93.459% (-1.2%) from 94.616%
16095334159

Pull #39

github

kaidokert
I think we won
Pull Request #39: Streambuffer debug

445 of 512 new or added lines in 5 files covered. (86.91%)

9 existing lines in 1 file now uncovered.

4101 of 4388 relevant lines covered (93.46%)

523.52 hits per line

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

85.67
/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 -= offset; // Normal 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 -= offset; // Normal 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 -= offset; // Normal 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 = if offset > content_start {
×
NEW
553
            offset - content_start
×
554
        } else {
NEW
555
            0
×
556
        };
557

NEW
558
        if discarded_content > 0 {
×
559
            // We lost some actual key content - this would require content recovery
560
            // For now, this is unsupported
NEW
561
            return Err(ParseError::ScratchBufferFull);
×
UNCOV
562
        }
×
563

564
        // No actual content was discarded, we can continue parsing
565
        // We can continue parsing the key from the current position
NEW
566
        Ok(())
×
NEW
567
    }
×
568

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

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

580
        // Calculate how much actual string content was discarded
NEW
581
        let content_start = original_pos; // String content starts at original_pos (now tracks content directly)
×
NEW
582
        let discarded_content = if offset > content_start {
×
NEW
583
            offset - content_start
×
584
        } else {
NEW
585
            0
×
586
        };
587

NEW
588
        if discarded_content > 0 {
×
589
            // We lost some actual string content - this would require content recovery
590
            // For now, this is unsupported
NEW
591
            return Err(ParseError::ScratchBufferFull);
×
NEW
592
        }
×
593

594
        // No actual content was discarded, we can continue parsing
595
        // We can continue parsing the string from the current position
UNCOV
596
        Ok(())
×
UNCOV
597
    }
×
598

599
    /// Handle byte accumulation for strings/keys and Unicode escape sequences
600
    fn handle_byte_accumulation(&mut self, byte: u8) -> Result<(), ParseError> {
10,807✔
601
        // Check if we're in a string or key state
602
        let in_string_mode = matches!(
10,807✔
603
            self.parser_state.state,
10,807✔
604
            crate::shared::State::String(_) | crate::shared::State::Key(_)
605
        );
606

607
        if in_string_mode {
10,807✔
608
            // Access escape state from enum
609
            let in_escape = if let ProcessingState::Active {
6,072✔
610
                in_escape_sequence, ..
6,072✔
611
            } = &self.processing_state
6,072✔
612
            {
613
                *in_escape_sequence
6,072✔
614
            } else {
615
                false
×
616
            };
617

618
            // Normal byte accumulation - all escape processing now goes through event system
619
            if !in_escape && self.stream_buffer.has_unescaped_content() {
6,072✔
620
                self.append_byte_to_escape_buffer(byte)?;
377✔
621
            }
5,695✔
622
        }
4,735✔
623

624
        Ok(())
10,807✔
625
    }
10,807✔
626

627
    /// Start escape processing using StreamBuffer
628
    fn start_escape_processing(&mut self) -> Result<(), ParseError> {
798✔
629
        // Update escape state in enum
630
        if let ProcessingState::Active {
631
            ref mut in_escape_sequence,
798✔
632
            ..
633
        } = self.processing_state
798✔
634
        {
798✔
635
            *in_escape_sequence = true;
798✔
636
        }
798✔
637

638
        // Initialize escape processing with StreamBuffer if not already started
639
        if !self.stream_buffer.has_unescaped_content() {
798✔
640
            if let crate::shared::State::String(start_pos) | crate::shared::State::Key(start_pos) =
266✔
641
                self.parser_state.state
266✔
642
            {
643
                let current_pos = self.stream_buffer.current_position();
266✔
644

645
                // With content tracking, start_pos is the content_start
646
                let content_start = start_pos;
266✔
647
                // Content to copy ends right before the escape character
648
                let content_end = ContentRange::end_position_excluding_delimiter(current_pos);
266✔
649

650
                // Estimate max length needed for unescaping (content so far + remaining buffer)
651
                let content_len = content_end.wrapping_sub(content_start);
266✔
652
                let max_escaped_len = self
266✔
653
                    .stream_buffer
266✔
654
                    .remaining_bytes()
266✔
655
                    .checked_add(content_len)
266✔
656
                    .ok_or(ParseError::NumericOverflow)?;
266✔
657

658
                // Start unescaping with StreamBuffer and copy existing content
659
                self.stream_buffer.start_unescaping_with_copy(
266✔
660
                    max_escaped_len,
266✔
661
                    content_start,
266✔
662
                    content_end,
266✔
663
                )?;
×
664
            }
×
665
        }
532✔
666

667
        Ok(())
798✔
668
    }
798✔
669

670
    /// Handle simple escape sequence using unified EscapeProcessor
671
    fn handle_simple_escape(&mut self, escape_token: &EventToken) -> Result<(), ParseError> {
657✔
672
        // Update escape state in enum
673
        if let ProcessingState::Active {
674
            ref mut in_escape_sequence,
657✔
675
            ..
676
        } = self.processing_state
657✔
677
        {
657✔
678
            *in_escape_sequence = false;
657✔
679
        }
657✔
680

681
        // Use unified escape token processing from EscapeProcessor
682
        if let Ok(unescaped_char) = EscapeProcessor::process_escape_token(escape_token) {
657✔
683
            self.append_byte_to_escape_buffer(unescaped_char)?;
657✔
684
        }
×
685

686
        Ok(())
657✔
687
    }
657✔
688

689
    /// Extracts hex digits from buffer and processes them through the collector
690
    fn process_unicode_escape_with_collector(&mut self) -> Result<(), ParseError> {
81✔
691
        // Update escape state in enum - Unicode escape processing is complete
692
        if let ProcessingState::Active {
693
            ref mut in_escape_sequence,
81✔
694
            ..
695
        } = self.processing_state
81✔
696
        {
81✔
697
            *in_escape_sequence = false;
81✔
698
        }
81✔
699

700
        let utf8_bytes_copy = {
81✔
701
            let current_pos = self.stream_buffer.current_position();
81✔
702
            let hex_slice_provider = |start, end| {
81✔
703
                self.stream_buffer
81✔
704
                    .get_string_slice(start, end)
81✔
705
                    .map_err(Into::into)
81✔
706
            };
81✔
707

708
            let mut utf8_buf = [0u8; 4];
81✔
709
            let (utf8_bytes, _escape_start_pos) =
81✔
710
                crate::escape_processor::process_unicode_escape_sequence(
81✔
711
                    current_pos,
81✔
712
                    &mut self.unicode_escape_collector,
81✔
713
                    hex_slice_provider,
81✔
714
                    &mut utf8_buf,
81✔
715
                )?;
×
716
            let mut copy = [0u8; 4];
81✔
717
            let len = utf8_bytes.len();
81✔
718
            if let Some(dest) = copy.get_mut(..len) {
81✔
719
                dest.copy_from_slice(utf8_bytes);
81✔
720
            }
81✔
721
            (copy, len)
81✔
722
        };
723

724
        if let Some(bytes_to_copy) = utf8_bytes_copy.0.get(..utf8_bytes_copy.1) {
81✔
725
            for &byte in bytes_to_copy {
321✔
726
                self.append_byte_to_escape_buffer(byte)?;
240✔
727
            }
728
        }
×
729
        Ok(())
81✔
730
    }
81✔
731

732
    /// Append a byte to the StreamBuffer's unescaped content
733
    fn append_byte_to_escape_buffer(&mut self, byte: u8) -> Result<(), ParseError> {
1,274✔
734
        self.stream_buffer
1,274✔
735
            .append_unescaped_byte(byte)
1,274✔
736
            .map_err(|e| e.into())
1,274✔
737
    }
1,274✔
738

739
    /// Queue a reset of unescaped content for the next next_event() call
740
    fn queue_unescaped_reset(&mut self) {
152✔
741
        // Set the reset flag in the Active state
742
        if let ProcessingState::Active {
743
            ref mut unescaped_reset_queued,
152✔
744
            ..
745
        } = self.processing_state
152✔
746
        {
152✔
747
            *unescaped_reset_queued = true;
152✔
748
        }
152✔
749
    }
152✔
750

751
    /// Apply queued unescaped content reset if flag is set
752
    fn apply_unescaped_reset_if_queued(&mut self) {
4,760✔
753
        // Check the enum field first
754
        let should_reset = if let ProcessingState::Active {
4,760✔
755
            ref mut unescaped_reset_queued,
4,756✔
756
            ..
757
        } = self.processing_state
4,760✔
758
        {
759
            let needs_reset = *unescaped_reset_queued;
4,756✔
760
            *unescaped_reset_queued = false; // Clear the flag
4,756✔
761
            needs_reset
4,756✔
762
        } else {
763
            false
4✔
764
        };
765

766
        if should_reset {
4,760✔
767
            self.stream_buffer.clear_unescaped();
125✔
768
        }
4,635✔
769
    }
4,760✔
770
}
771

772
impl<'b, R: Reader, C: BitStackConfig> PullParser for StreamParser<'b, R, C> {
773
    fn next_event(&mut self) -> Result<Event<'_, '_>, ParseError> {
4,760✔
774
        self.next_event_impl()
4,760✔
775
    }
4,760✔
776
}
777

778
#[cfg(test)]
779
mod tests {
780
    use super::*;
781

782
    /// Simple test reader that reads from a byte slice
783
    pub struct SliceReader<'a> {
784
        data: &'a [u8],
785
        position: usize,
786
    }
787

788
    impl<'a> SliceReader<'a> {
789
        pub fn new(data: &'a [u8]) -> Self {
39✔
790
            Self { data, position: 0 }
39✔
791
        }
39✔
792
    }
793

794
    impl Reader for SliceReader<'_> {
795
        type Error = ();
796

797
        fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
69✔
798
            let remaining = self.data.len().saturating_sub(self.position);
69✔
799
            if remaining == 0 {
69✔
800
                return Ok(0); // EOF
30✔
801
            }
39✔
802

803
            let to_copy = remaining.min(buf.len());
39✔
804
            let end_pos = self.position.saturating_add(to_copy);
39✔
805
            if let (Some(dest), Some(src)) = (
39✔
806
                buf.get_mut(..to_copy),
39✔
807
                self.data.get(self.position..end_pos),
39✔
808
            ) {
809
                dest.copy_from_slice(src);
39✔
810
                self.position = end_pos;
39✔
811
                Ok(to_copy)
39✔
812
            } else {
813
                Err(())
×
814
            }
815
        }
69✔
816
    }
817

818
    type TestStreamParser<'b> = StreamParser<'b, SliceReader<'static>>;
819

820
    #[test]
821
    fn test_direct_parser_simple_object() {
1✔
822
        let json = b"{}";
1✔
823
        let reader = SliceReader::new(json);
1✔
824
        let mut buffer = [0u8; 256];
1✔
825
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
826

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

831
        // Should get ObjectEnd
832
        let event = parser.next_event().unwrap();
1✔
833
        assert!(matches!(event, Event::EndObject));
1✔
834

835
        // Should get EndDocument
836
        let event = parser.next_event().unwrap();
1✔
837
        assert!(matches!(event, Event::EndDocument));
1✔
838
    }
1✔
839

840
    #[test]
841
    fn test_direct_parser_simple_array() {
1✔
842
        let json = b"[]";
1✔
843
        let reader = SliceReader::new(json);
1✔
844
        let mut buffer = [0u8; 256];
1✔
845
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
846

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

851
        // Should get ArrayEnd
852
        let event = parser.next_event().unwrap();
1✔
853
        assert!(matches!(event, Event::EndArray));
1✔
854

855
        // Should get EndDocument
856
        let event = parser.next_event().unwrap();
1✔
857
        assert!(matches!(event, Event::EndDocument));
1✔
858
    }
1✔
859

860
    #[test]
861
    fn test_direct_parser_simple_escape() {
1✔
862
        let json = b"\"hello\\nworld\"";
1✔
863
        let reader = SliceReader::new(json);
1✔
864
        let mut buffer = [0u8; 256];
1✔
865
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
866

867
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
868
            assert_eq!(json_string.as_str(), "hello\nworld");
1✔
869
        } else {
870
            panic!("Expected String event");
×
871
        }
872
    }
1✔
873

874
    #[test]
875
    fn test_pending_state_edge_cases() {
1✔
876
        // Test 1: Complex nested container endings
877
        let json1 = br#"{"a": {"b": [{"c": 123}]}}"#;
1✔
878
        let reader1 = SliceReader::new(json1);
1✔
879
        let mut buffer1 = [0u8; 256];
1✔
880
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
881

882
        let mut events = Vec::new();
1✔
883
        loop {
884
            match parser1.next_event() {
13✔
885
                Ok(Event::EndDocument) => break,
1✔
886
                Ok(event) => events.push(format!("{:?}", event)),
12✔
887
                Err(e) => panic!("Nested containers failed: {:?}", e),
×
888
            }
889
        }
890

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

894
        // Test 2: Mixed types after numbers in array
895
        let json2 = br#"[123, "string", true, null, 456]"#;
1✔
896
        let reader2 = SliceReader::new(json2);
1✔
897
        let mut buffer2 = [0u8; 256];
1✔
898
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
899

900
        let mut number_count = 0;
1✔
901
        loop {
902
            match parser2.next_event() {
8✔
903
                Ok(Event::EndDocument) => break,
1✔
904
                Ok(Event::Number(_)) => number_count += 1,
2✔
905
                Ok(_) => {}
5✔
906
                Err(e) => panic!("Mixed types failed: {:?}", e),
×
907
            }
908
        }
909
        assert_eq!(number_count, 2); // Should find both 123 and 456
1✔
910

911
        // Test 3: Empty containers
912
        let json3 = br#"[[], {}, [{}], {"empty": []}]"#;
1✔
913
        let reader3 = SliceReader::new(json3);
1✔
914
        let mut buffer3 = [0u8; 256];
1✔
915
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
916

917
        loop {
918
            match parser3.next_event() {
16✔
919
                Ok(Event::EndDocument) => break,
1✔
920
                Ok(_) => {}
15✔
921
                Err(e) => panic!("Empty containers failed: {:?}", e),
×
922
            }
923
        }
924

925
        // Test 4: Multiple consecutive numbers
926
        let json4 = br#"[1, 2, 3, 4, 5]"#;
1✔
927
        let reader4 = SliceReader::new(json4);
1✔
928
        let mut buffer4 = [0u8; 256];
1✔
929
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
1✔
930

931
        let mut consecutive_numbers = Vec::new();
1✔
932
        loop {
933
            match parser4.next_event() {
8✔
934
                Ok(Event::EndDocument) => break,
1✔
935
                Ok(Event::Number(n)) => consecutive_numbers.push(n.as_str().to_string()),
5✔
936
                Ok(_) => {}
2✔
937
                Err(e) => panic!("Consecutive numbers failed: {:?}", e),
×
938
            }
939
        }
940
        assert_eq!(consecutive_numbers, vec!["1", "2", "3", "4", "5"]);
1✔
941
    }
1✔
942

943
    #[test]
944
    fn test_error_recovery_with_pending_state() {
1✔
945
        // Test error handling - this should fail gracefully without hanging onto pending state
946
        let invalid_json = br#"{"key": 123,"#; // Missing closing brace
1✔
947
        let reader = SliceReader::new(invalid_json);
1✔
948
        let mut buffer = [0u8; 256];
1✔
949
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
950

951
        // Parse until we hit an error or EOF
952
        loop {
953
            match parser.next_event() {
4✔
954
                Ok(Event::EndDocument) => break, // EOF reached
×
955
                Ok(_) => {}
3✔
956
                Err(_) => break, // Error occurred - this is expected
1✔
957
            }
958
        }
959

960
        // The important thing is that we don't panic or hang
961
        // The specific error behavior may vary
962
    }
1✔
963

964
    #[test]
965
    fn test_multiple_rapid_container_ends() {
1✔
966
        // Test deeply nested structures that end with numbers
967
        // This tests whether we can handle multiple rapid container ends correctly
968

969
        // Test 1: Deeply nested arrays ending with number
970
        let json1 = br#"[[[123]]]"#;
1✔
971
        let reader1 = SliceReader::new(json1);
1✔
972
        let mut buffer1 = [0u8; 256];
1✔
973
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
974

975
        let mut events1 = Vec::new();
1✔
976
        loop {
977
            match parser1.next_event() {
8✔
978
                Ok(Event::EndDocument) => break,
1✔
979
                Ok(event) => events1.push(format!("{:?}", event)),
7✔
980
                Err(e) => panic!("Deeply nested arrays failed: {:?}", e),
×
981
            }
982
        }
983

984
        // Should have: StartArray, StartArray, StartArray, Number(123), EndArray, EndArray, EndArray
985
        assert_eq!(events1.len(), 7);
1✔
986
        assert!(events1[3].contains("Number"));
1✔
987
        assert_eq!(&events1[4], "EndArray");
1✔
988
        assert_eq!(&events1[5], "EndArray");
1✔
989
        assert_eq!(&events1[6], "EndArray");
1✔
990

991
        // Test 2: Mixed nested containers ending with number
992
        let json2 = br#"{"a": [{"b": 456}]}"#;
1✔
993
        let reader2 = SliceReader::new(json2);
1✔
994
        let mut buffer2 = [0u8; 256];
1✔
995
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
996

997
        let mut events2 = Vec::new();
1✔
998
        loop {
999
            match parser2.next_event() {
10✔
1000
                Ok(Event::EndDocument) => break,
1✔
1001
                Ok(event) => events2.push(format!("{:?}", event)),
9✔
1002
                Err(e) => panic!("Mixed nested containers failed: {:?}", e),
×
1003
            }
1004
        }
1005

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

1009
        // Test 3: Multiple numbers at different nesting levels
1010
        let json3 = br#"[123, [456, [789]]]"#;
1✔
1011
        let reader3 = SliceReader::new(json3);
1✔
1012
        let mut buffer3 = [0u8; 256];
1✔
1013
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
1014

1015
        let mut number_count = 0;
1✔
1016
        let mut events3 = Vec::new();
1✔
1017
        loop {
1018
            match parser3.next_event() {
10✔
1019
                Ok(Event::EndDocument) => break,
1✔
1020
                Ok(Event::Number(n)) => {
3✔
1021
                    number_count += 1;
3✔
1022
                    events3.push(format!("Number({})", n.as_str()));
3✔
1023
                }
3✔
1024
                Ok(event) => events3.push(format!("{:?}", event)),
6✔
1025
                Err(e) => panic!("Multiple nested numbers failed: {:?}", e),
×
1026
            }
1027
        }
1028

1029
        assert_eq!(number_count, 3); // Should find all three numbers: 123, 456, 789
1✔
1030
    }
1✔
1031

1032
    #[test]
1033
    fn test_pending_flag_priority() {
1✔
1034
        // Defensive test: ensure that if both pending flags were somehow set,
1035
        // we handle it gracefully (this shouldn't happen in normal operation)
1036

1037
        let json = br#"[{"key": 123}]"#;
1✔
1038
        let reader = SliceReader::new(json);
1✔
1039
        let mut buffer = [0u8; 256];
1✔
1040
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1041

1042
        // Parse normally - this should work fine and never set both flags
1043
        let mut events = Vec::new();
1✔
1044
        loop {
1045
            match parser.next_event() {
7✔
1046
                Ok(Event::EndDocument) => break,
1✔
1047
                Ok(event) => events.push(format!("{:?}", event)),
6✔
1048
                Err(e) => panic!("Flag priority test failed: {:?}", e),
×
1049
            }
1050
        }
1051

1052
        // Should successfully parse: StartArray, StartObject, Key, Number, EndObject, EndArray
1053
        assert_eq!(events.len(), 6);
1✔
1054
        assert!(events[3].contains("Number"));
1✔
1055
        assert_eq!(&events[4], "EndObject");
1✔
1056
        assert_eq!(&events[5], "EndArray");
1✔
1057
    }
1✔
1058

1059
    #[test]
1060
    fn test_direct_parser_array_of_strings() {
1✔
1061
        let json = b"[\"first\", \"second\"]";
1✔
1062
        let reader = SliceReader::new(json);
1✔
1063
        let mut buffer = [0u8; 256];
1✔
1064
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1065

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

1068
        if let Event::String(s1) = parser.next_event().unwrap() {
1✔
1069
            assert_eq!(s1.as_str(), "first");
1✔
1070
        } else {
1071
            panic!("Expected String event");
×
1072
        }
1073

1074
        if let Event::String(s2) = parser.next_event().unwrap() {
1✔
1075
            assert_eq!(s2.as_str(), "second");
1✔
1076
        } else {
1077
            panic!("Expected String event");
×
1078
        }
1079

1080
        assert!(matches!(parser.next_event().unwrap(), Event::EndArray));
1✔
1081
    }
1✔
1082

1083
    #[test]
1084
    fn test_direct_parser_object_with_keys() {
1✔
1085
        let json = b"{\"name\": \"value\", \"count\": \"42\"}";
1✔
1086
        let reader = SliceReader::new(json);
1✔
1087
        let mut buffer = [0u8; 256];
1✔
1088
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1089

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

1092
        // First key-value pair
1093
        if let Event::Key(key1) = parser.next_event().unwrap() {
1✔
1094
            assert_eq!(key1.as_str(), "name");
1✔
1095
        } else {
1096
            panic!("Expected Key event");
×
1097
        }
1098

1099
        if let Event::String(val1) = parser.next_event().unwrap() {
1✔
1100
            assert_eq!(val1.as_str(), "value");
1✔
1101
        } else {
1102
            panic!("Expected String event");
×
1103
        }
1104

1105
        // Second key-value pair
1106
        if let Event::Key(key2) = parser.next_event().unwrap() {
1✔
1107
            assert_eq!(key2.as_str(), "count");
1✔
1108
        } else {
1109
            panic!("Expected Key event");
×
1110
        }
1111

1112
        if let Event::String(val2) = parser.next_event().unwrap() {
1✔
1113
            assert_eq!(val2.as_str(), "42");
1✔
1114
        } else {
1115
            panic!("Expected String event");
×
1116
        }
1117

1118
        assert!(matches!(parser.next_event().unwrap(), Event::EndObject));
1✔
1119
    }
1✔
1120

1121
    #[test]
1122
    fn test_direct_parser_multiple_escapes() {
1✔
1123
        let json = b"\"line1\\nline2\\ttab\\\"quote\"";
1✔
1124
        let reader = SliceReader::new(json);
1✔
1125
        let mut buffer = [0u8; 256];
1✔
1126
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1127

1128
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
1129
            let content = json_string.as_str();
1✔
1130
            // Check that escape sequences were properly processed
1131
            let has_newline = content.contains('\n');
1✔
1132
            let has_tab = content.contains('\t');
1✔
1133
            let has_quote = content.contains('"');
1✔
1134

1135
            // These should be real control characters, not literal \n \t \"
1136
            assert!(has_newline, "Should contain actual newline character");
1✔
1137
            assert!(has_tab, "Should contain actual tab character");
1✔
1138
            assert!(has_quote, "Should contain actual quote character");
1✔
1139
        } else {
1140
            panic!("Expected String event");
×
1141
        }
1142
    }
1✔
1143

1144
    #[test]
1145
    fn test_direct_parser_unicode_escape() {
1✔
1146
        let json = b"\"Hello \\u0041\\u03B1\""; // Hello A(alpha)
1✔
1147
        let reader = SliceReader::new(json);
1✔
1148
        let mut buffer = [0u8; 256];
1✔
1149
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1150

1151
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
1152
            let content = json_string.as_str();
1✔
1153
            // Should be "Hello A⍺" (with actual A and alpha characters)
1154
            assert!(content.contains('A'));
1✔
1155
            // Note: This test will initially fail until we implement Unicode escapes
1156
        } else {
1157
            panic!("Expected String event");
×
1158
        }
1159
    }
1✔
1160

1161
    #[test]
1162
    fn test_direct_parser_boolean_true() {
1✔
1163
        let json = b"true";
1✔
1164
        let reader = SliceReader::new(json);
1✔
1165
        let mut buffer = [0u8; 256];
1✔
1166
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1167

1168
        let event = parser.next_event().unwrap();
1✔
1169
        assert_eq!(event, Event::Bool(true));
1✔
1170

1171
        let event = parser.next_event().unwrap();
1✔
1172
        assert_eq!(event, Event::EndDocument);
1✔
1173
    }
1✔
1174

1175
    #[test]
1176
    fn test_direct_parser_boolean_false() {
1✔
1177
        let json = b"false";
1✔
1178
        let reader = SliceReader::new(json);
1✔
1179
        let mut buffer = [0u8; 256];
1✔
1180
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1181

1182
        let event = parser.next_event().unwrap();
1✔
1183
        assert_eq!(event, Event::Bool(false));
1✔
1184

1185
        let event = parser.next_event().unwrap();
1✔
1186
        assert_eq!(event, Event::EndDocument);
1✔
1187
    }
1✔
1188

1189
    #[test]
1190
    fn test_direct_parser_null() {
1✔
1191
        let json = b"null";
1✔
1192
        let reader = SliceReader::new(json);
1✔
1193
        let mut buffer = [0u8; 256];
1✔
1194
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1195

1196
        let event = parser.next_event().unwrap();
1✔
1197
        assert_eq!(event, Event::Null);
1✔
1198

1199
        let event = parser.next_event().unwrap();
1✔
1200
        assert_eq!(event, Event::EndDocument);
1✔
1201
    }
1✔
1202

1203
    #[test]
1204
    fn test_direct_parser_booleans_in_array() {
1✔
1205
        let json = b"[true, false, null]";
1✔
1206
        let reader = SliceReader::new(json);
1✔
1207
        let mut buffer = [0u8; 256];
1✔
1208
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1209

1210
        assert_eq!(parser.next_event().unwrap(), Event::StartArray);
1✔
1211
        assert_eq!(parser.next_event().unwrap(), Event::Bool(true));
1✔
1212
        assert_eq!(parser.next_event().unwrap(), Event::Bool(false));
1✔
1213
        assert_eq!(parser.next_event().unwrap(), Event::Null);
1✔
1214
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1✔
1215
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1216
    }
1✔
1217

1218
    #[test]
1219
    fn test_direct_parser_number_simple() {
1✔
1220
        let json = b"42";
1✔
1221
        let reader = SliceReader::new(json);
1✔
1222
        let mut buffer = [0u8; 256];
1✔
1223
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1224

1225
        let event = parser.next_event().unwrap();
1✔
1226
        if let Event::Number(json_number) = event {
1✔
1227
            assert_eq!(json_number.as_str(), "42");
1✔
1228
        } else {
1229
            panic!("Expected Number event, got: {:?}", event);
×
1230
        }
1231

1232
        let event = parser.next_event().unwrap();
1✔
1233
        assert_eq!(event, Event::EndDocument);
1✔
1234
    }
1✔
1235

1236
    #[test]
1237
    fn test_direct_parser_number_negative() {
1✔
1238
        let json = b"-123";
1✔
1239
        let reader = SliceReader::new(json);
1✔
1240
        let mut buffer = [0u8; 256];
1✔
1241
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1242

1243
        let event = parser.next_event().unwrap();
1✔
1244
        if let Event::Number(json_number) = event {
1✔
1245
            assert_eq!(json_number.as_str(), "-123");
1✔
1246
        } else {
1247
            panic!("Expected Number event, got: {:?}", event);
×
1248
        }
1249

1250
        let event = parser.next_event().unwrap();
1✔
1251
        assert_eq!(event, Event::EndDocument);
1✔
1252
    }
1✔
1253

1254
    #[test]
1255
    fn test_direct_parser_number_float() {
1✔
1256
        let json = b"3.14159";
1✔
1257
        let reader = SliceReader::new(json);
1✔
1258
        let mut buffer = [0u8; 256];
1✔
1259
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1260

1261
        #[cfg(feature = "float-error")]
1262
        {
1263
            // float-error configuration should return an error for float values
1264
            let result = parser.next_event();
1265
            assert!(
1266
                result.is_err(),
1267
                "Expected error for float with float-error configuration"
1268
            );
1269
            return;
1270
        }
1271

1272
        #[cfg(not(feature = "float-error"))]
1273
        {
1274
            let event = parser.next_event().unwrap();
1✔
1275
            if let Event::Number(json_number) = event {
1✔
1276
                assert_eq!(json_number.as_str(), "3.14159");
1✔
1277
            } else {
1278
                panic!("Expected Number event, got: {:?}", event);
×
1279
            }
1280

1281
            let event = parser.next_event().unwrap();
1✔
1282
            assert_eq!(event, Event::EndDocument);
1✔
1283
        }
1284
    }
1✔
1285

1286
    #[test]
1287
    fn test_direct_parser_numbers_in_array() {
1✔
1288
        #[cfg(feature = "float-error")]
1289
        let json = b"[42, -7]"; // No floats for float-error config
1290
        #[cfg(not(feature = "float-error"))]
1291
        let json = b"[42, -7, 3.14]"; // Include float for other configs
1✔
1292

1293
        let reader = SliceReader::new(json);
1✔
1294
        let mut buffer = [0u8; 256];
1✔
1295
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1296

1297
        assert_eq!(parser.next_event().unwrap(), Event::StartArray);
1✔
1298

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

1306
        let event = parser.next_event().unwrap();
1✔
1307
        if let Event::Number(json_number) = event {
1✔
1308
            assert_eq!(json_number.as_str(), "-7");
1✔
1309
        } else {
1310
            panic!("Expected Number event, got: {:?}", event);
×
1311
        }
1312

1313
        #[cfg(not(feature = "float-error"))]
1314
        {
1315
            let event = parser.next_event().unwrap();
1✔
1316
            if let Event::Number(json_number) = event {
1✔
1317
                assert_eq!(json_number.as_str(), "3.14");
1✔
1318
            } else {
1319
                panic!("Expected Number event, got: {:?}", event);
×
1320
            }
1321
        }
1322

1323
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1✔
1324
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1325
    }
1✔
1326

1327
    #[test]
1328
    fn test_direct_parser_numbers_in_object() {
1✔
1329
        #[cfg(feature = "float-error")]
1330
        let json = b"{\"count\": 42, \"score\": -7}"; // No floats for float-error config
1331
        #[cfg(not(feature = "float-error"))]
1332
        let json = b"{\"count\": 42, \"score\": -7.5}"; // Include float for other configs
1✔
1333

1334
        let reader = SliceReader::new(json);
1✔
1335
        let mut buffer = [0u8; 256];
1✔
1336
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1337

1338
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1339

1340
        // First key-value pair
1341
        if let Event::Key(key1) = parser.next_event().unwrap() {
1✔
1342
            assert_eq!(key1.as_str(), "count");
1✔
1343
        } else {
1344
            panic!("Expected Key event");
×
1345
        }
1346

1347
        if let Event::Number(val1) = parser.next_event().unwrap() {
1✔
1348
            assert_eq!(val1.as_str(), "42");
1✔
1349
        } else {
1350
            panic!("Expected Number event");
×
1351
        }
1352

1353
        // Second key-value pair
1354
        if let Event::Key(key2) = parser.next_event().unwrap() {
1✔
1355
            assert_eq!(key2.as_str(), "score");
1✔
1356
        } else {
1357
            panic!("Expected Key event");
×
1358
        }
1359

1360
        if let Event::Number(val2) = parser.next_event().unwrap() {
1✔
1361
            #[cfg(feature = "float-error")]
1362
            assert_eq!(val2.as_str(), "-7");
1363
            #[cfg(not(feature = "float-error"))]
1364
            assert_eq!(val2.as_str(), "-7.5");
1✔
1365
        } else {
1366
            panic!("Expected Number event");
×
1367
        }
1368

1369
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1370
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1371
    }
1✔
1372

1373
    #[test]
1374
    fn test_direct_parser_no_float_configuration() {
1✔
1375
        // Test that StreamParser properly uses unified number parsing with no-float config
1376
        let json = br#"{"integer": 42, "float": 3.14, "scientific": 1e3}"#;
1✔
1377
        let reader = SliceReader::new(json);
1✔
1378
        let mut buffer = [0u8; 256];
1✔
1379
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1380

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

1384
        // Integer key-value
1385
        assert_eq!(
1✔
1386
            parser.next_event().unwrap(),
1✔
1387
            Event::Key(crate::String::Borrowed("integer"))
1388
        );
1389
        if let Event::Number(num) = parser.next_event().unwrap() {
1✔
1390
            assert_eq!(num.as_str(), "42");
1✔
1391
            match num.parsed() {
1✔
1392
                crate::NumberResult::Integer(i) => assert_eq!(*i, 42),
1✔
1393
                _ => panic!("Expected integer parsing"),
×
1394
            }
1395
        } else {
1396
            panic!("Expected Number event");
×
1397
        }
1398

1399
        // Float key-value - behavior varies by configuration
1400
        assert_eq!(
1✔
1401
            parser.next_event().unwrap(),
1✔
1402
            Event::Key(crate::String::Borrowed("float"))
1403
        );
1404

1405
        #[cfg(feature = "float-error")]
1406
        {
1407
            // float-error should return an error when encountering floats
1408
            let result = parser.next_event();
1409
            assert!(
1410
                result.is_err(),
1411
                "Expected error for float with float-error configuration"
1412
            );
1413
            // Test ends here for float-error - no more processing needed
1414
        }
1415

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

1446
            // Scientific notation handling varies by float configuration
1447
            assert_eq!(
1✔
1448
                parser.next_event().unwrap(),
1✔
1449
                Event::Key(crate::String::Borrowed("scientific"))
1450
            );
1451

1452
            // float-truncate rejects scientific notation, so test should end early for that config
1453
            #[cfg(feature = "float-truncate")]
1454
            {
1455
                // float-truncate rejects scientific notation since it would require float math
1456
                let result = parser.next_event();
1457
                assert!(
1458
                    result.is_err(),
1459
                    "Expected error for scientific notation with float-truncate"
1460
                );
1461
                // Test ends here for float-truncate - no more processing needed
1462
            }
1463

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

1488
                assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1489
                assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1490
            }
1491
        }
1492
    }
1✔
1493

1494
    #[test]
1495
    fn test_number_parsing_delimiter_exclusion() {
1✔
1496
        // Test that numbers don't include trailing delimiters in various contexts
1497

1498
        // Test 1: Number followed by array end
1499
        let json1 = b"[123]";
1✔
1500
        let reader1 = SliceReader::new(json1);
1✔
1501
        let mut buffer1 = [0u8; 256];
1✔
1502
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
1503

1504
        assert!(matches!(parser1.next_event().unwrap(), Event::StartArray));
1✔
1505
        if let Event::Number(num) = parser1.next_event().unwrap() {
1✔
1506
            assert_eq!(
1✔
1507
                num.as_str(),
1✔
1508
                "123",
1509
                "Number should not include trailing delimiter ']'"
×
1510
            );
1511
        } else {
1512
            panic!("Expected Number event");
×
1513
        }
1514
        assert!(matches!(parser1.next_event().unwrap(), Event::EndArray));
1✔
1515

1516
        // Test 2: Number followed by object end
1517
        let json2 = b"{\"key\":456}";
1✔
1518
        let reader2 = SliceReader::new(json2);
1✔
1519
        let mut buffer2 = [0u8; 256];
1✔
1520
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
1521

1522
        assert!(matches!(parser2.next_event().unwrap(), Event::StartObject));
1✔
1523
        assert!(matches!(parser2.next_event().unwrap(), Event::Key(_)));
1✔
1524
        if let Event::Number(num) = parser2.next_event().unwrap() {
1✔
1525
            assert_eq!(
1✔
1526
                num.as_str(),
1✔
1527
                "456",
1528
                "Number should not include trailing delimiter '}}'"
×
1529
            );
1530
        } else {
1531
            panic!("Expected Number event");
×
1532
        }
1533
        assert!(matches!(parser2.next_event().unwrap(), Event::EndObject));
1✔
1534

1535
        // Test 3: Number followed by comma in array
1536
        let json3 = b"[789,10]";
1✔
1537
        let reader3 = SliceReader::new(json3);
1✔
1538
        let mut buffer3 = [0u8; 256];
1✔
1539
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
1540

1541
        assert!(matches!(parser3.next_event().unwrap(), Event::StartArray));
1✔
1542
        if let Event::Number(num1) = parser3.next_event().unwrap() {
1✔
1543
            assert_eq!(
1✔
1544
                num1.as_str(),
1✔
1545
                "789",
1546
                "First number should not include trailing delimiter ','"
×
1547
            );
1548
        } else {
1549
            panic!("Expected first Number event");
×
1550
        }
1551
        if let Event::Number(num2) = parser3.next_event().unwrap() {
1✔
1552
            assert_eq!(
1✔
1553
                num2.as_str(),
1✔
1554
                "10",
1555
                "Second number should not include trailing delimiter ']'"
×
1556
            );
1557
        } else {
1558
            panic!("Expected second Number event");
×
1559
        }
1560
        assert!(matches!(parser3.next_event().unwrap(), Event::EndArray));
1✔
1561

1562
        // Test 4: Number followed by comma in object
1563
        let json4 = b"{\"a\":11,\"b\":22}";
1✔
1564
        let reader4 = SliceReader::new(json4);
1✔
1565
        let mut buffer4 = [0u8; 256];
1✔
1566
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
1✔
1567

1568
        assert!(matches!(parser4.next_event().unwrap(), Event::StartObject));
1✔
1569
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1✔
1570
        if let Event::Number(num1) = parser4.next_event().unwrap() {
1✔
1571
            assert_eq!(
1✔
1572
                num1.as_str(),
1✔
1573
                "11",
1574
                "First number should not include trailing delimiter ','"
×
1575
            );
1576
        } else {
1577
            panic!("Expected first Number event");
×
1578
        }
1579
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1✔
1580
        if let Event::Number(num2) = parser4.next_event().unwrap() {
1✔
1581
            assert_eq!(
1✔
1582
                num2.as_str(),
1✔
1583
                "22",
1584
                "Second number should not include trailing delimiter '}}'"
×
1585
            );
1586
        } else {
1587
            panic!("Expected second Number event");
×
1588
        }
1589
        assert!(matches!(parser4.next_event().unwrap(), Event::EndObject));
1✔
1590

1591
        // Test 5: Standalone number at end of document (should include full content)
1592
        let json5 = b"999";
1✔
1593
        let reader5 = SliceReader::new(json5);
1✔
1594
        let mut buffer5 = [0u8; 256];
1✔
1595
        let mut parser5 = TestStreamParser::new(reader5, &mut buffer5);
1✔
1596

1597
        if let Event::Number(num) = parser5.next_event().unwrap() {
1✔
1598
            assert_eq!(
1✔
1599
                num.as_str(),
1✔
1600
                "999",
1601
                "Standalone number should include full content"
×
1602
            );
1603
        } else {
1604
            panic!("Expected Number event");
×
1605
        }
1606
        assert!(matches!(parser5.next_event().unwrap(), Event::EndDocument));
1✔
1607

1608
        // Test 6: Negative numbers with delimiters
1609
        let json6 = b"[-42,33]";
1✔
1610
        let reader6 = SliceReader::new(json6);
1✔
1611
        let mut buffer6 = [0u8; 256];
1✔
1612
        let mut parser6 = TestStreamParser::new(reader6, &mut buffer6);
1✔
1613

1614
        assert!(matches!(parser6.next_event().unwrap(), Event::StartArray));
1✔
1615
        if let Event::Number(num1) = parser6.next_event().unwrap() {
1✔
1616
            assert_eq!(
1✔
1617
                num1.as_str(),
1✔
1618
                "-42",
1619
                "Negative number should not include trailing delimiter ','"
×
1620
            );
1621
        } else {
1622
            panic!("Expected first Number event");
×
1623
        }
1624
        if let Event::Number(num2) = parser6.next_event().unwrap() {
1✔
1625
            assert_eq!(
1✔
1626
                num2.as_str(),
1✔
1627
                "33",
1628
                "Second number should not include trailing delimiter ']'"
×
1629
            );
1630
        } else {
1631
            panic!("Expected second Number event");
×
1632
        }
1633
        assert!(matches!(parser6.next_event().unwrap(), Event::EndArray));
1✔
1634

1635
        // Test 7: Decimal numbers with delimiters (if float enabled)
1636
        #[cfg(not(feature = "float-error"))]
1637
        {
1638
            let json7 = b"[3.14,2.71]";
1✔
1639
            let reader7 = SliceReader::new(json7);
1✔
1640
            let mut buffer7 = [0u8; 256];
1✔
1641
            let mut parser7 = TestStreamParser::new(reader7, &mut buffer7);
1✔
1642

1643
            assert!(matches!(parser7.next_event().unwrap(), Event::StartArray));
1✔
1644
            if let Event::Number(num1) = parser7.next_event().unwrap() {
1✔
1645
                assert_eq!(
1✔
1646
                    num1.as_str(),
1✔
1647
                    "3.14",
1648
                    "Decimal number should not include trailing delimiter ','"
×
1649
                );
1650
            } else {
1651
                panic!("Expected first Number event");
×
1652
            }
1653
            if let Event::Number(num2) = parser7.next_event().unwrap() {
1✔
1654
                assert_eq!(
1✔
1655
                    num2.as_str(),
1✔
1656
                    "2.71",
1657
                    "Second decimal number should not include trailing delimiter ']'"
×
1658
                );
1659
            } else {
1660
                panic!("Expected second Number event");
×
1661
            }
1662
            assert!(matches!(parser7.next_event().unwrap(), Event::EndArray));
1✔
1663
        }
1664
    }
1✔
1665

1666
    #[test]
1667
    fn test_escape_buffer_functions() {
1✔
1668
        // Test the uncovered escape processing functions
1669
        let json_stream = br#"{"escaped": "test\nstring"}"#;
1✔
1670
        let mut buffer = [0u8; 1024];
1✔
1671
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1✔
1672

1673
        // These functions are private but we can test them through the public API
1674
        // The escape processing should trigger the uncovered functions
1675
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1676
        assert_eq!(
1✔
1677
            parser.next_event().unwrap(),
1✔
1678
            Event::Key(crate::String::Borrowed("escaped"))
1679
        );
1680

1681
        // This should trigger append_byte_to_escape_buffer and queue_unescaped_reset
1682
        if let Event::String(s) = parser.next_event().unwrap() {
1✔
1683
            assert_eq!(s.as_ref(), "test\nstring"); // Escape sequence should be processed
1✔
1684
        } else {
1685
            panic!("Expected String event with escape sequence");
×
1686
        }
1687

1688
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1689
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1690
    }
1✔
1691

1692
    #[test]
1693
    fn test_slice_reader_constructor() {
1✔
1694
        // Test the uncovered SliceReader::new function
1695
        let data = b"test data";
1✔
1696
        let reader = SliceReader::new(data);
1✔
1697
        assert_eq!(reader.data, data);
1✔
1698
        assert_eq!(reader.position, 0);
1✔
1699
    }
1✔
1700

1701
    #[test]
1702
    fn test_complex_escape_sequences() {
1✔
1703
        // Test more complex escape processing to cover the escape buffer functions
1704
        let json_stream = br#"{"multi": "line1\nline2\ttab\r\n"}"#;
1✔
1705
        let mut buffer = [0u8; 1024];
1✔
1706
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1✔
1707

1708
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1709
        assert_eq!(
1✔
1710
            parser.next_event().unwrap(),
1✔
1711
            Event::Key(crate::String::Borrowed("multi"))
1712
        );
1713

1714
        // This should exercise the escape buffer processing extensively
1715
        if let Event::String(s) = parser.next_event().unwrap() {
1✔
1716
            assert_eq!(s.as_ref(), "line1\nline2\ttab\r\n");
1✔
1717
        } else {
1718
            panic!("Expected String event");
×
1719
        }
1720

1721
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1722
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1723
    }
1✔
1724

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

1731
        println!("Testing escape sequence with buffer size: {}", buffer_size);
3✔
1732
        println!(
3✔
1733
            "JSON input: {:?}",
3✔
1734
            core::str::from_utf8(json_stream).unwrap()
3✔
1735
        );
1736
        let mut buffer = vec![0u8; buffer_size];
3✔
1737
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
3✔
1738

1739
        // Array start
1740
        match parser.next_event()? {
3✔
1741
            Event::StartArray => println!("  ✅ StartArray OK"),
3✔
NEW
1742
            other => panic!("Expected StartArray, got: {:?}", other),
×
1743
        }
1744

1745
        // String with escape
1746
        match parser.next_event()? {
3✔
1747
            Event::String(s) => {
2✔
1748
                println!("  ✅ String OK: '{}'", s.as_str());
2✔
1749
                assert_eq!(s.as_str(), "hello\\");
2✔
1750
            }
NEW
1751
            other => panic!("Expected String, got: {:?}", other),
×
1752
        }
1753

1754
        // Array end
1755
        match parser.next_event()? {
2✔
1756
            Event::EndArray => println!("  ✅ EndArray OK"),
2✔
NEW
1757
            other => panic!("Expected EndArray, got: {:?}", other),
×
1758
        }
1759

1760
        // End document
1761
        match parser.next_event()? {
2✔
1762
            Event::EndDocument => println!("  ✅ EndDocument OK"),
2✔
NEW
1763
            other => panic!("Expected EndDocument, got: {:?}", other),
×
1764
        }
1765

1766
        println!("  🎉 SUCCESS with buffer size: {}", buffer_size);
2✔
1767
        Ok(())
2✔
1768
    }
3✔
1769

1770
    #[test]
1771
    fn test_minimal_buffer_simple_escape_1() {
1✔
1772
        // Buffer size 4 - clearly not enough
1773
        match test_simple_escape_with_buffer_size(4) {
1✔
NEW
1774
            Ok(()) => panic!("Expected failure with 4-byte buffer, but succeeded!"),
×
1775
            Err(e) => println!("Expected failure with 4-byte buffer: {:?}", e),
1✔
1776
        }
1777
    }
1✔
1778

1779
    #[test]
1780
    fn test_minimal_buffer_simple_escape_2() {
1✔
1781
        // Buffer size 12 - test if larger buffer avoids compaction bugs
1782
        test_simple_escape_with_buffer_size(12)
1✔
1783
            .expect("12-byte buffer should be sufficient for simple escape");
1✔
1784
    }
1✔
1785

1786
    #[test]
1787
    fn test_minimal_buffer_simple_escape_3() {
1✔
1788
        // Buffer size 24 - known working boundary from stress tests
1789
        test_simple_escape_with_buffer_size(24).expect("24-byte buffer should definitely work");
1✔
1790
    }
1✔
1791
}
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