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

kaidokert / picojson-rs / 16092023061

05 Jul 2025 09:02PM UTC coverage: 94.616% (+0.3%) from 94.304%
16092023061

Pull #38

github

kaidokert
Rename direct_buffer->stream_buffer
Pull Request #38: General refactor and cleanup

68 of 78 new or added lines in 2 files covered. (87.18%)

80 existing lines in 2 files now uncovered.

3743 of 3956 relevant lines covered (94.62%)

80.45 hits per line

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

89.98
/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 {
36✔
68
        Self::with_config(reader, buffer)
36✔
69
    }
36✔
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 {
38✔
107
        Self {
38✔
108
            tokenizer: Tokenizer::new(),
38✔
109
            parser_state: ParserState::new(),
38✔
110
            reader,
38✔
111
            stream_buffer: StreamBuffer::new(buffer),
38✔
112

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

38✔
119
            unicode_escape_collector: UnicodeEscapeCollector::new(),
38✔
120
        }
38✔
121
    }
38✔
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> {
195✔
128
        // Apply any queued unescaped content reset from previous call
129
        self.apply_unescaped_reset_if_queued();
195✔
130

131
        loop {
132
            // Pull events from tokenizer until we have some
133
            while !self.have_events() {
903✔
134
                // Fill buffer and check for end of data
135
                self.fill_buffer_from_reader()?;
621✔
136

137
                if self.stream_buffer.is_empty() {
621✔
138
                    // Handle end of data with tokenizer finish
139
                    if !matches!(self.processing_state, ProcessingState::Finished) {
31✔
140
                        self.processing_state = ProcessingState::Finished;
27✔
141

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

154
                        if self.tokenizer.finish(&mut callback).is_err() {
27✔
155
                            return Err(ParseError::TokenizerError);
1✔
156
                        }
26✔
157
                    }
4✔
158

159
                    if !self.have_events() {
30✔
160
                        return Ok(Event::EndDocument);
26✔
161
                    }
4✔
162
                    // Continue to process any events generated by finish()
163
                } else {
164
                    // Get byte and advance
165
                    let byte = self.stream_buffer.current_byte()?;
590✔
166
                    self.stream_buffer.advance()?;
590✔
167

168
                    // Process byte through tokenizer
169
                    self.clear_events();
590✔
170
                    let mut callback = |event, _len| {
590✔
171
                        // Store events in the array, filling available slots
172
                        for evt in self.parser_state.evts.iter_mut() {
304✔
173
                            if evt.is_none() {
304✔
174
                                *evt = Some(event);
278✔
175
                                return;
278✔
176
                            }
26✔
177
                        }
178
                    };
278✔
179

180
                    if self.tokenizer.parse_chunk(&[byte], &mut callback).is_err() {
590✔
181
                        return Err(ParseError::TokenizerError);
×
182
                    }
590✔
183

184
                    // Special case processing removed - let all escape handling go through event system
185

186
                    // Handle byte accumulation if no event was generated
187
                    if !self.have_events() {
590✔
188
                        self.handle_byte_accumulation(byte)?;
338✔
189
                    }
252✔
190
                }
191
            }
192

193
            // Now we have events - process ONE event
194
            let taken_event = self.parser_state.evts.iter_mut().find_map(|e| e.take());
308✔
195

196
            if let Some(taken_event) = taken_event {
282✔
197
                // Process the event directly in the main loop
198
                match taken_event {
103✔
199
                    // Container events
200
                    ujson::Event::ObjectStart => return Ok(Event::StartObject),
20✔
201
                    ujson::Event::ObjectEnd => return Ok(Event::EndObject),
19✔
202
                    ujson::Event::ArrayStart => return Ok(Event::StartArray),
24✔
203
                    ujson::Event::ArrayEnd => return Ok(Event::EndArray),
24✔
204

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

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

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

241
                    // Number events
242
                    ujson::Event::Begin(
243
                        EventToken::Number
244
                        | EventToken::NumberAndArray
245
                        | EventToken::NumberAndObject,
246
                    ) => {
38✔
247
                        // Update parser state to track number position
38✔
248
                        let current_pos = self.stream_buffer.current_position();
38✔
249
                        let number_start = ContentRange::number_start_from_current(current_pos);
38✔
250
                        self.parser_state.state = crate::shared::State::Number(number_start);
38✔
251
                        // Continue processing
38✔
252
                    }
38✔
253
                    ujson::Event::End(EventToken::Number) => {
254
                        // Extract number content from parser state (standalone number)
255
                        return self.extract_number_from_state();
21✔
256
                    }
257
                    ujson::Event::End(EventToken::NumberAndArray) => {
258
                        // Extract number content (came from container delimiter)
259
                        return self.extract_number_from_state_with_context(true);
9✔
260
                    }
261
                    ujson::Event::End(EventToken::NumberAndObject) => {
262
                        // Extract number content (came from container delimiter)
263
                        return self.extract_number_from_state_with_context(true);
8✔
264
                    }
265

266
                    // Escape sequence handling
267
                    ujson::Event::Begin(EventToken::EscapeSequence) => {
268
                        // Start of escape sequence - we'll handle escapes by unescaping to buffer
269
                        self.start_escape_processing()?;
11✔
270
                        // Continue processing
271
                    }
272
                    ujson::Event::End(
273
                        escape_token @ (EventToken::EscapeQuote
9✔
274
                        | EventToken::EscapeBackslash
275
                        | EventToken::EscapeSlash
276
                        | EventToken::EscapeBackspace
277
                        | EventToken::EscapeFormFeed
278
                        | EventToken::EscapeNewline
279
                        | EventToken::EscapeCarriageReturn
280
                        | EventToken::EscapeTab),
281
                    ) => {
282
                        // Handle simple escape sequences
283
                        self.handle_simple_escape(&escape_token)?;
9✔
284
                        // Continue processing
285
                    }
286
                    ujson::Event::Begin(EventToken::UnicodeEscape) => {
287
                        // Start Unicode escape collection - reset collector for new sequence
288
                        // Only handle if we're inside a string or key
289
                        match self.parser_state.state {
2✔
290
                            crate::shared::State::String(_) | crate::shared::State::Key(_) => {
2✔
291
                                self.unicode_escape_collector.reset();
2✔
292
                            }
2✔
293
                            _ => {}
×
294
                        }
295
                        // Continue processing
296
                    }
297
                    ujson::Event::End(EventToken::UnicodeEscape) => {
298
                        // Handle end of Unicode escape sequence (\\uXXXX)
299
                        match self.parser_state.state {
2✔
300
                            crate::shared::State::String(_) | crate::shared::State::Key(_) => {
301
                                self.process_unicode_escape_with_collector()?;
2✔
302
                            }
303
                            _ => {}
×
304
                        }
305
                        // Continue processing
306
                    }
307

308
                    // All other events - continue processing
309
                    _ => {
9✔
310
                        // Continue to next byte
9✔
311
                    }
9✔
312
                }
313
            }
×
314
            // If no event was processed, continue the outer loop to get more events
315
        }
316
    }
195✔
317

318
    /// Check if we have events waiting to be processed
319
    fn have_events(&self) -> bool {
1,523✔
320
        self.parser_state.evts.iter().any(|evt| evt.is_some())
2,534✔
321
    }
1,523✔
322

323
    /// Extract number from parser state without 'static lifetime cheating
324
    fn extract_number_from_state(&mut self) -> Result<Event<'_, '_>, ParseError> {
21✔
325
        self.extract_number_from_state_with_context(false)
21✔
326
    }
21✔
327

328
    /// Extract string after all buffer operations are complete
329
    fn extract_string_from_state(&mut self) -> Result<Event<'_, '_>, ParseError> {
11✔
330
        let crate::shared::State::String(start_pos) = self.parser_state.state else {
11✔
331
            return Err(ParserErrorHandler::state_mismatch("string", "extract"));
×
332
        };
333

334
        self.parser_state.state = crate::shared::State::None;
11✔
335

336
        if self.stream_buffer.has_unescaped_content() {
11✔
337
            self.create_unescaped_string()
5✔
338
        } else {
339
            self.create_borrowed_string(start_pos)
6✔
340
        }
341
    }
11✔
342

343
    /// Helper to create an unescaped string from StreamBuffer
344
    fn create_unescaped_string(&mut self) -> Result<Event<'_, '_>, ParseError> {
5✔
345
        self.queue_unescaped_reset();
5✔
346
        let unescaped_slice = self.stream_buffer.get_unescaped_slice()?;
5✔
347
        let str_content = crate::shared::from_utf8(unescaped_slice)?;
5✔
348
        Ok(Event::String(crate::String::Unescaped(str_content)))
5✔
349
    }
5✔
350

351
    /// Helper to create a borrowed string from StreamBuffer
352
    fn create_borrowed_string(&mut self, start_pos: usize) -> Result<Event<'_, '_>, ParseError> {
6✔
353
        let current_pos = self.stream_buffer.current_position();
6✔
354
        let (content_start, content_end) =
6✔
355
            ContentRange::string_content_bounds(start_pos, current_pos);
6✔
356

357
        let bytes = self
6✔
358
            .stream_buffer
6✔
359
            .get_string_slice(content_start, content_end)?;
6✔
360
        let str_content = crate::shared::from_utf8(bytes)?;
6✔
361
        Ok(Event::String(crate::String::Borrowed(str_content)))
6✔
362
    }
6✔
363

364
    /// Extract key after all buffer operations are complete
365
    fn extract_key_from_state(&mut self) -> Result<Event<'_, '_>, ParseError> {
22✔
366
        let crate::shared::State::Key(start_pos) = self.parser_state.state else {
22✔
367
            return Err(ParserErrorHandler::state_mismatch("key", "extract"));
×
368
        };
369

370
        self.parser_state.state = crate::shared::State::None;
22✔
371

372
        if self.stream_buffer.has_unescaped_content() {
22✔
373
            self.create_unescaped_key()
×
374
        } else {
375
            self.create_borrowed_key(start_pos)
22✔
376
        }
377
    }
22✔
378

379
    /// Helper to create an unescaped key from StreamBuffer
380
    fn create_unescaped_key(&mut self) -> Result<Event<'_, '_>, ParseError> {
×
381
        self.queue_unescaped_reset();
×
NEW
382
        let unescaped_slice = self.stream_buffer.get_unescaped_slice()?;
×
383
        let str_content = crate::shared::from_utf8(unescaped_slice)?;
×
384
        Ok(Event::Key(crate::String::Unescaped(str_content)))
×
385
    }
×
386

387
    /// Helper to create a borrowed key from StreamBuffer
388
    fn create_borrowed_key(&mut self, start_pos: usize) -> Result<Event<'_, '_>, ParseError> {
22✔
389
        let current_pos = self.stream_buffer.current_position();
22✔
390
        let (content_start, content_end) =
22✔
391
            ContentRange::string_content_bounds(start_pos, current_pos);
22✔
392

393
        let bytes = self
22✔
394
            .stream_buffer
22✔
395
            .get_string_slice(content_start, content_end)?;
22✔
396
        let str_content = crate::shared::from_utf8(bytes)?;
22✔
397
        Ok(Event::Key(crate::String::Borrowed(str_content)))
22✔
398
    }
22✔
399

400
    /// Extract number with delimiter context using unified parsing logic
401
    fn extract_number_from_state_with_context(
38✔
402
        &mut self,
38✔
403
        from_container_end: bool,
38✔
404
    ) -> Result<Event<'_, '_>, ParseError> {
38✔
405
        let crate::shared::State::Number(start_pos) = self.parser_state.state else {
38✔
406
            return Err(ParserErrorHandler::state_mismatch("number", "extract"));
×
407
        };
408

409
        self.parser_state.state = crate::shared::State::None;
38✔
410

411
        // Use unified number parsing logic
412
        crate::number_parser::parse_number_event(&self.stream_buffer, start_pos, from_container_end)
38✔
413
    }
38✔
414
    /// Clear event slots
415
    fn clear_events(&mut self) {
617✔
416
        self.parser_state.evts[0] = None;
617✔
417
        self.parser_state.evts[1] = None;
617✔
418
    }
617✔
419

420
    /// Fill buffer from reader
421
    fn fill_buffer_from_reader(&mut self) -> Result<(), ParseError> {
621✔
422
        if let Some(fill_slice) = self.stream_buffer.get_fill_slice() {
621✔
423
            let bytes_read = self
621✔
424
                .reader
621✔
425
                .read(fill_slice)
621✔
426
                .map_err(|_| ParseError::ReaderError)?;
621✔
427

428
            self.stream_buffer.mark_filled(bytes_read)?;
621✔
429

430
            // Note: bytes_read == 0 indicates end-of-stream per trait contract.
431
            // The main loop will handle transitioning to Finished state when buffer is empty.
432
        }
×
433
        Ok(())
621✔
434
    }
621✔
435

436
    /// Handle byte accumulation for strings/keys and Unicode escape sequences
437
    fn handle_byte_accumulation(&mut self, byte: u8) -> Result<(), ParseError> {
338✔
438
        // Check if we're in a string or key state
439
        let in_string_mode = matches!(
338✔
440
            self.parser_state.state,
338✔
441
            crate::shared::State::String(_) | crate::shared::State::Key(_)
442
        );
443

444
        if in_string_mode {
338✔
445
            // Access escape state from enum
446
            let in_escape = if let ProcessingState::Active {
174✔
447
                in_escape_sequence, ..
174✔
448
            } = &self.processing_state
174✔
449
            {
450
                *in_escape_sequence
174✔
451
            } else {
452
                false
×
453
            };
454

455
            // Normal byte accumulation - all escape processing now goes through event system
456
            if !in_escape && self.stream_buffer.has_unescaped_content() {
174✔
457
                self.append_byte_to_escape_buffer(byte)?;
32✔
458
            }
142✔
459
        }
164✔
460

461
        Ok(())
338✔
462
    }
338✔
463

464
    /// Start escape processing using StreamBuffer
465
    fn start_escape_processing(&mut self) -> Result<(), ParseError> {
11✔
466
        // Update escape state in enum
467
        if let ProcessingState::Active {
468
            ref mut in_escape_sequence,
11✔
469
            ..
470
        } = self.processing_state
11✔
471
        {
11✔
472
            *in_escape_sequence = true;
11✔
473
        }
11✔
474

475
        // Initialize escape processing with StreamBuffer if not already started
476
        if !self.stream_buffer.has_unescaped_content() {
11✔
477
            if let crate::shared::State::String(start_pos) | crate::shared::State::Key(start_pos) =
5✔
478
                self.parser_state.state
5✔
479
            {
480
                let current_pos = self.stream_buffer.current_position();
5✔
481
                let (content_start, content_end) =
5✔
482
                    ContentRange::string_content_bounds_before_escape(start_pos, current_pos);
5✔
483

484
                // Estimate max length needed for unescaping (content so far + remaining buffer)
485
                let content_len = content_end.wrapping_sub(content_start);
5✔
486
                let max_escaped_len = self
5✔
487
                    .stream_buffer
5✔
488
                    .remaining_bytes()
5✔
489
                    .checked_add(content_len)
5✔
490
                    .ok_or(ParseError::NumericOverflow)?;
5✔
491

492
                // Start unescaping with StreamBuffer and copy existing content
493
                self.stream_buffer.start_unescaping_with_copy(
5✔
494
                    max_escaped_len,
5✔
495
                    content_start,
5✔
496
                    content_end,
5✔
497
                )?;
×
498
            }
×
499
        }
6✔
500

501
        Ok(())
11✔
502
    }
11✔
503

504
    /// Handle simple escape sequence using unified EscapeProcessor
505
    fn handle_simple_escape(&mut self, escape_token: &EventToken) -> Result<(), ParseError> {
9✔
506
        // Update escape state in enum
507
        if let ProcessingState::Active {
508
            ref mut in_escape_sequence,
9✔
509
            ..
510
        } = self.processing_state
9✔
511
        {
9✔
512
            *in_escape_sequence = false;
9✔
513
        }
9✔
514

515
        // Use unified escape token processing from EscapeProcessor
516
        if let Ok(unescaped_char) = EscapeProcessor::process_escape_token(escape_token) {
9✔
517
            self.append_byte_to_escape_buffer(unescaped_char)?;
9✔
518
        }
×
519

520
        Ok(())
9✔
521
    }
9✔
522

523
    /// Extracts hex digits from buffer and processes them through the collector
524
    fn process_unicode_escape_with_collector(&mut self) -> Result<(), ParseError> {
2✔
525
        // Update escape state in enum - Unicode escape processing is complete
526
        if let ProcessingState::Active {
527
            ref mut in_escape_sequence,
2✔
528
            ..
529
        } = self.processing_state
2✔
530
        {
2✔
531
            *in_escape_sequence = false;
2✔
532
        }
2✔
533

534
        let utf8_bytes_copy = {
2✔
535
            let current_pos = self.stream_buffer.current_position();
2✔
536
            let hex_slice_provider = |start, end| {
2✔
537
                self.stream_buffer
2✔
538
                    .get_string_slice(start, end)
2✔
539
                    .map_err(Into::into)
2✔
540
            };
2✔
541

542
            let mut utf8_buf = [0u8; 4];
2✔
543
            let (utf8_bytes, _escape_start_pos) =
2✔
544
                crate::escape_processor::process_unicode_escape_sequence(
2✔
545
                    current_pos,
2✔
546
                    &mut self.unicode_escape_collector,
2✔
547
                    hex_slice_provider,
2✔
548
                    &mut utf8_buf,
2✔
549
                )?;
×
550
            let mut copy = [0u8; 4];
2✔
551
            let len = utf8_bytes.len();
2✔
552
            if let Some(dest) = copy.get_mut(..len) {
2✔
553
                dest.copy_from_slice(utf8_bytes);
2✔
554
            }
2✔
555
            (copy, len)
2✔
556
        };
557

558
        if let Some(bytes_to_copy) = utf8_bytes_copy.0.get(..utf8_bytes_copy.1) {
2✔
559
            for &byte in bytes_to_copy {
5✔
560
                self.append_byte_to_escape_buffer(byte)?;
3✔
561
            }
562
        }
×
563
        Ok(())
2✔
564
    }
2✔
565

566
    /// Append a byte to the StreamBuffer's unescaped content
567
    fn append_byte_to_escape_buffer(&mut self, byte: u8) -> Result<(), ParseError> {
44✔
568
        self.stream_buffer
44✔
569
            .append_unescaped_byte(byte)
44✔
570
            .map_err(|e| e.into())
44✔
571
    }
44✔
572

573
    /// Queue a reset of unescaped content for the next next_event() call
574
    fn queue_unescaped_reset(&mut self) {
5✔
575
        // Set the reset flag in the Active state
576
        if let ProcessingState::Active {
577
            ref mut unescaped_reset_queued,
5✔
578
            ..
579
        } = self.processing_state
5✔
580
        {
5✔
581
            *unescaped_reset_queued = true;
5✔
582
        }
5✔
583
    }
5✔
584

585
    /// Apply queued unescaped content reset if flag is set
586
    fn apply_unescaped_reset_if_queued(&mut self) {
195✔
587
        // Check the enum field first
588
        let should_reset = if let ProcessingState::Active {
195✔
589
            ref mut unescaped_reset_queued,
191✔
590
            ..
591
        } = self.processing_state
195✔
592
        {
593
            let needs_reset = *unescaped_reset_queued;
191✔
594
            *unescaped_reset_queued = false; // Clear the flag
191✔
595
            needs_reset
191✔
596
        } else {
597
            false
4✔
598
        };
599

600
        if should_reset {
195✔
601
            self.stream_buffer.clear_unescaped();
2✔
602
        }
193✔
603
    }
195✔
604
}
605

606
impl<'b, R: Reader, C: BitStackConfig> PullParser for StreamParser<'b, R, C> {
607
    fn next_event(&mut self) -> Result<Event<'_, '_>, ParseError> {
195✔
608
        self.next_event_impl()
195✔
609
    }
195✔
610
}
611

612
#[cfg(test)]
613
mod tests {
614
    use super::*;
615

616
    /// Simple test reader that reads from a byte slice
617
    pub struct SliceReader<'a> {
618
        data: &'a [u8],
619
        position: usize,
620
    }
621

622
    impl<'a> SliceReader<'a> {
623
        pub fn new(data: &'a [u8]) -> Self {
36✔
624
            Self { data, position: 0 }
36✔
625
        }
36✔
626
    }
627

628
    impl Reader for SliceReader<'_> {
629
        type Error = ();
630

631
        fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
576✔
632
            let remaining = self.data.len().saturating_sub(self.position);
576✔
633
            if remaining == 0 {
576✔
634
                return Ok(0); // EOF
541✔
635
            }
35✔
636

637
            let to_copy = remaining.min(buf.len());
35✔
638
            let end_pos = self.position.saturating_add(to_copy);
35✔
639
            if let (Some(dest), Some(src)) = (
35✔
640
                buf.get_mut(..to_copy),
35✔
641
                self.data.get(self.position..end_pos),
35✔
642
            ) {
643
                dest.copy_from_slice(src);
35✔
644
                self.position = end_pos;
35✔
645
                Ok(to_copy)
35✔
646
            } else {
647
                Err(())
×
648
            }
649
        }
576✔
650
    }
651

652
    type TestStreamParser<'b> = StreamParser<'b, SliceReader<'static>>;
653

654
    #[test]
655
    fn test_direct_parser_simple_object() {
1✔
656
        let json = b"{}";
1✔
657
        let reader = SliceReader::new(json);
1✔
658
        let mut buffer = [0u8; 256];
1✔
659
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
660

661
        // Should get ObjectStart
662
        let event = parser.next_event().unwrap();
1✔
663
        assert!(matches!(event, Event::StartObject));
1✔
664

665
        // Should get ObjectEnd
666
        let event = parser.next_event().unwrap();
1✔
667
        assert!(matches!(event, Event::EndObject));
1✔
668

669
        // Should get EndDocument
670
        let event = parser.next_event().unwrap();
1✔
671
        assert!(matches!(event, Event::EndDocument));
1✔
672
    }
1✔
673

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

681
        // Should get ArrayStart
682
        let event = parser.next_event().unwrap();
1✔
683
        assert!(matches!(event, Event::StartArray));
1✔
684

685
        // Should get ArrayEnd
686
        let event = parser.next_event().unwrap();
1✔
687
        assert!(matches!(event, Event::EndArray));
1✔
688

689
        // Should get EndDocument
690
        let event = parser.next_event().unwrap();
1✔
691
        assert!(matches!(event, Event::EndDocument));
1✔
692
    }
1✔
693

694
    #[test]
695
    fn test_direct_parser_simple_escape() {
1✔
696
        let json = b"\"hello\\nworld\"";
1✔
697
        let reader = SliceReader::new(json);
1✔
698
        let mut buffer = [0u8; 256];
1✔
699
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
700

701
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
702
            assert_eq!(json_string.as_str(), "hello\nworld");
1✔
703
        } else {
UNCOV
704
            panic!("Expected String event");
×
705
        }
706
    }
1✔
707

708
    #[test]
709
    fn test_pending_state_edge_cases() {
1✔
710
        // Test 1: Complex nested container endings
711
        let json1 = br#"{"a": {"b": [{"c": 123}]}}"#;
1✔
712
        let reader1 = SliceReader::new(json1);
1✔
713
        let mut buffer1 = [0u8; 256];
1✔
714
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
715

716
        let mut events = Vec::new();
1✔
717
        loop {
718
            match parser1.next_event() {
13✔
719
                Ok(Event::EndDocument) => break,
1✔
720
                Ok(event) => events.push(format!("{:?}", event)),
12✔
UNCOV
721
                Err(e) => panic!("Nested containers failed: {:?}", e),
×
722
            }
723
        }
724

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

728
        // Test 2: Mixed types after numbers in array
729
        let json2 = br#"[123, "string", true, null, 456]"#;
1✔
730
        let reader2 = SliceReader::new(json2);
1✔
731
        let mut buffer2 = [0u8; 256];
1✔
732
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
733

734
        let mut number_count = 0;
1✔
735
        loop {
736
            match parser2.next_event() {
8✔
737
                Ok(Event::EndDocument) => break,
1✔
738
                Ok(Event::Number(_)) => number_count += 1,
2✔
739
                Ok(_) => {}
5✔
UNCOV
740
                Err(e) => panic!("Mixed types failed: {:?}", e),
×
741
            }
742
        }
743
        assert_eq!(number_count, 2); // Should find both 123 and 456
1✔
744

745
        // Test 3: Empty containers
746
        let json3 = br#"[[], {}, [{}], {"empty": []}]"#;
1✔
747
        let reader3 = SliceReader::new(json3);
1✔
748
        let mut buffer3 = [0u8; 256];
1✔
749
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
750

751
        loop {
752
            match parser3.next_event() {
16✔
753
                Ok(Event::EndDocument) => break,
1✔
754
                Ok(_) => {}
15✔
UNCOV
755
                Err(e) => panic!("Empty containers failed: {:?}", e),
×
756
            }
757
        }
758

759
        // Test 4: Multiple consecutive numbers
760
        let json4 = br#"[1, 2, 3, 4, 5]"#;
1✔
761
        let reader4 = SliceReader::new(json4);
1✔
762
        let mut buffer4 = [0u8; 256];
1✔
763
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
1✔
764

765
        let mut consecutive_numbers = Vec::new();
1✔
766
        loop {
767
            match parser4.next_event() {
8✔
768
                Ok(Event::EndDocument) => break,
1✔
769
                Ok(Event::Number(n)) => consecutive_numbers.push(n.as_str().to_string()),
5✔
770
                Ok(_) => {}
2✔
UNCOV
771
                Err(e) => panic!("Consecutive numbers failed: {:?}", e),
×
772
            }
773
        }
774
        assert_eq!(consecutive_numbers, vec!["1", "2", "3", "4", "5"]);
1✔
775
    }
1✔
776

777
    #[test]
778
    fn test_error_recovery_with_pending_state() {
1✔
779
        // Test error handling - this should fail gracefully without hanging onto pending state
780
        let invalid_json = br#"{"key": 123,"#; // Missing closing brace
1✔
781
        let reader = SliceReader::new(invalid_json);
1✔
782
        let mut buffer = [0u8; 256];
1✔
783
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
784

785
        // Parse until we hit an error or EOF
786
        loop {
787
            match parser.next_event() {
4✔
UNCOV
788
                Ok(Event::EndDocument) => break, // EOF reached
×
789
                Ok(_) => {}
3✔
790
                Err(_) => break, // Error occurred - this is expected
1✔
791
            }
792
        }
793

794
        // The important thing is that we don't panic or hang
795
        // The specific error behavior may vary
796
    }
1✔
797

798
    #[test]
799
    fn test_multiple_rapid_container_ends() {
1✔
800
        // Test deeply nested structures that end with numbers
801
        // This tests whether we can handle multiple rapid container ends correctly
802

803
        // Test 1: Deeply nested arrays ending with number
804
        let json1 = br#"[[[123]]]"#;
1✔
805
        let reader1 = SliceReader::new(json1);
1✔
806
        let mut buffer1 = [0u8; 256];
1✔
807
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
808

809
        let mut events1 = Vec::new();
1✔
810
        loop {
811
            match parser1.next_event() {
8✔
812
                Ok(Event::EndDocument) => break,
1✔
813
                Ok(event) => events1.push(format!("{:?}", event)),
7✔
UNCOV
814
                Err(e) => panic!("Deeply nested arrays failed: {:?}", e),
×
815
            }
816
        }
817

818
        // Should have: StartArray, StartArray, StartArray, Number(123), EndArray, EndArray, EndArray
819
        assert_eq!(events1.len(), 7);
1✔
820
        assert!(events1[3].contains("Number"));
1✔
821
        assert_eq!(&events1[4], "EndArray");
1✔
822
        assert_eq!(&events1[5], "EndArray");
1✔
823
        assert_eq!(&events1[6], "EndArray");
1✔
824

825
        // Test 2: Mixed nested containers ending with number
826
        let json2 = br#"{"a": [{"b": 456}]}"#;
1✔
827
        let reader2 = SliceReader::new(json2);
1✔
828
        let mut buffer2 = [0u8; 256];
1✔
829
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
830

831
        let mut events2 = Vec::new();
1✔
832
        loop {
833
            match parser2.next_event() {
10✔
834
                Ok(Event::EndDocument) => break,
1✔
835
                Ok(event) => events2.push(format!("{:?}", event)),
9✔
UNCOV
836
                Err(e) => panic!("Mixed nested containers failed: {:?}", e),
×
837
            }
838
        }
839

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

843
        // Test 3: Multiple numbers at different nesting levels
844
        let json3 = br#"[123, [456, [789]]]"#;
1✔
845
        let reader3 = SliceReader::new(json3);
1✔
846
        let mut buffer3 = [0u8; 256];
1✔
847
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
848

849
        let mut number_count = 0;
1✔
850
        let mut events3 = Vec::new();
1✔
851
        loop {
852
            match parser3.next_event() {
10✔
853
                Ok(Event::EndDocument) => break,
1✔
854
                Ok(Event::Number(n)) => {
3✔
855
                    number_count += 1;
3✔
856
                    events3.push(format!("Number({})", n.as_str()));
3✔
857
                }
3✔
858
                Ok(event) => events3.push(format!("{:?}", event)),
6✔
UNCOV
859
                Err(e) => panic!("Multiple nested numbers failed: {:?}", e),
×
860
            }
861
        }
862

863
        assert_eq!(number_count, 3); // Should find all three numbers: 123, 456, 789
1✔
864
    }
1✔
865

866
    #[test]
867
    fn test_pending_flag_priority() {
1✔
868
        // Defensive test: ensure that if both pending flags were somehow set,
869
        // we handle it gracefully (this shouldn't happen in normal operation)
870

871
        let json = br#"[{"key": 123}]"#;
1✔
872
        let reader = SliceReader::new(json);
1✔
873
        let mut buffer = [0u8; 256];
1✔
874
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
875

876
        // Parse normally - this should work fine and never set both flags
877
        let mut events = Vec::new();
1✔
878
        loop {
879
            match parser.next_event() {
7✔
880
                Ok(Event::EndDocument) => break,
1✔
881
                Ok(event) => events.push(format!("{:?}", event)),
6✔
UNCOV
882
                Err(e) => panic!("Flag priority test failed: {:?}", e),
×
883
            }
884
        }
885

886
        // Should successfully parse: StartArray, StartObject, Key, Number, EndObject, EndArray
887
        assert_eq!(events.len(), 6);
1✔
888
        assert!(events[3].contains("Number"));
1✔
889
        assert_eq!(&events[4], "EndObject");
1✔
890
        assert_eq!(&events[5], "EndArray");
1✔
891
    }
1✔
892

893
    #[test]
894
    fn test_direct_parser_array_of_strings() {
1✔
895
        let json = b"[\"first\", \"second\"]";
1✔
896
        let reader = SliceReader::new(json);
1✔
897
        let mut buffer = [0u8; 256];
1✔
898
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
899

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

902
        if let Event::String(s1) = parser.next_event().unwrap() {
1✔
903
            assert_eq!(s1.as_str(), "first");
1✔
904
        } else {
UNCOV
905
            panic!("Expected String event");
×
906
        }
907

908
        if let Event::String(s2) = parser.next_event().unwrap() {
1✔
909
            assert_eq!(s2.as_str(), "second");
1✔
910
        } else {
UNCOV
911
            panic!("Expected String event");
×
912
        }
913

914
        assert!(matches!(parser.next_event().unwrap(), Event::EndArray));
1✔
915
    }
1✔
916

917
    #[test]
918
    fn test_direct_parser_object_with_keys() {
1✔
919
        let json = b"{\"name\": \"value\", \"count\": \"42\"}";
1✔
920
        let reader = SliceReader::new(json);
1✔
921
        let mut buffer = [0u8; 256];
1✔
922
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
923

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

926
        // First key-value pair
927
        if let Event::Key(key1) = parser.next_event().unwrap() {
1✔
928
            assert_eq!(key1.as_str(), "name");
1✔
929
        } else {
UNCOV
930
            panic!("Expected Key event");
×
931
        }
932

933
        if let Event::String(val1) = parser.next_event().unwrap() {
1✔
934
            assert_eq!(val1.as_str(), "value");
1✔
935
        } else {
UNCOV
936
            panic!("Expected String event");
×
937
        }
938

939
        // Second key-value pair
940
        if let Event::Key(key2) = parser.next_event().unwrap() {
1✔
941
            assert_eq!(key2.as_str(), "count");
1✔
942
        } else {
UNCOV
943
            panic!("Expected Key event");
×
944
        }
945

946
        if let Event::String(val2) = parser.next_event().unwrap() {
1✔
947
            assert_eq!(val2.as_str(), "42");
1✔
948
        } else {
UNCOV
949
            panic!("Expected String event");
×
950
        }
951

952
        assert!(matches!(parser.next_event().unwrap(), Event::EndObject));
1✔
953
    }
1✔
954

955
    #[test]
956
    fn test_direct_parser_multiple_escapes() {
1✔
957
        let json = b"\"line1\\nline2\\ttab\\\"quote\"";
1✔
958
        let reader = SliceReader::new(json);
1✔
959
        let mut buffer = [0u8; 256];
1✔
960
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
961

962
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
963
            let content = json_string.as_str();
1✔
964
            // Check that escape sequences were properly processed
965
            let has_newline = content.contains('\n');
1✔
966
            let has_tab = content.contains('\t');
1✔
967
            let has_quote = content.contains('"');
1✔
968

969
            // These should be real control characters, not literal \n \t \"
970
            assert!(has_newline, "Should contain actual newline character");
1✔
971
            assert!(has_tab, "Should contain actual tab character");
1✔
972
            assert!(has_quote, "Should contain actual quote character");
1✔
973
        } else {
UNCOV
974
            panic!("Expected String event");
×
975
        }
976
    }
1✔
977

978
    #[test]
979
    fn test_direct_parser_unicode_escape() {
1✔
980
        let json = b"\"Hello \\u0041\\u03B1\""; // Hello A(alpha)
1✔
981
        let reader = SliceReader::new(json);
1✔
982
        let mut buffer = [0u8; 256];
1✔
983
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
984

985
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
986
            let content = json_string.as_str();
1✔
987
            // Should be "Hello A⍺" (with actual A and alpha characters)
988
            assert!(content.contains('A'));
1✔
989
            // Note: This test will initially fail until we implement Unicode escapes
990
        } else {
UNCOV
991
            panic!("Expected String event");
×
992
        }
993
    }
1✔
994

995
    #[test]
996
    fn test_direct_parser_boolean_true() {
1✔
997
        let json = b"true";
1✔
998
        let reader = SliceReader::new(json);
1✔
999
        let mut buffer = [0u8; 256];
1✔
1000
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1001

1002
        let event = parser.next_event().unwrap();
1✔
1003
        assert_eq!(event, Event::Bool(true));
1✔
1004

1005
        let event = parser.next_event().unwrap();
1✔
1006
        assert_eq!(event, Event::EndDocument);
1✔
1007
    }
1✔
1008

1009
    #[test]
1010
    fn test_direct_parser_boolean_false() {
1✔
1011
        let json = b"false";
1✔
1012
        let reader = SliceReader::new(json);
1✔
1013
        let mut buffer = [0u8; 256];
1✔
1014
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1015

1016
        let event = parser.next_event().unwrap();
1✔
1017
        assert_eq!(event, Event::Bool(false));
1✔
1018

1019
        let event = parser.next_event().unwrap();
1✔
1020
        assert_eq!(event, Event::EndDocument);
1✔
1021
    }
1✔
1022

1023
    #[test]
1024
    fn test_direct_parser_null() {
1✔
1025
        let json = b"null";
1✔
1026
        let reader = SliceReader::new(json);
1✔
1027
        let mut buffer = [0u8; 256];
1✔
1028
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1029

1030
        let event = parser.next_event().unwrap();
1✔
1031
        assert_eq!(event, Event::Null);
1✔
1032

1033
        let event = parser.next_event().unwrap();
1✔
1034
        assert_eq!(event, Event::EndDocument);
1✔
1035
    }
1✔
1036

1037
    #[test]
1038
    fn test_direct_parser_booleans_in_array() {
1✔
1039
        let json = b"[true, false, null]";
1✔
1040
        let reader = SliceReader::new(json);
1✔
1041
        let mut buffer = [0u8; 256];
1✔
1042
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1043

1044
        assert_eq!(parser.next_event().unwrap(), Event::StartArray);
1✔
1045
        assert_eq!(parser.next_event().unwrap(), Event::Bool(true));
1✔
1046
        assert_eq!(parser.next_event().unwrap(), Event::Bool(false));
1✔
1047
        assert_eq!(parser.next_event().unwrap(), Event::Null);
1✔
1048
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1✔
1049
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1050
    }
1✔
1051

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

1059
        let event = parser.next_event().unwrap();
1✔
1060
        if let Event::Number(json_number) = event {
1✔
1061
            assert_eq!(json_number.as_str(), "42");
1✔
1062
        } else {
UNCOV
1063
            panic!("Expected Number event, got: {:?}", event);
×
1064
        }
1065

1066
        let event = parser.next_event().unwrap();
1✔
1067
        assert_eq!(event, Event::EndDocument);
1✔
1068
    }
1✔
1069

1070
    #[test]
1071
    fn test_direct_parser_number_negative() {
1✔
1072
        let json = b"-123";
1✔
1073
        let reader = SliceReader::new(json);
1✔
1074
        let mut buffer = [0u8; 256];
1✔
1075
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1076

1077
        let event = parser.next_event().unwrap();
1✔
1078
        if let Event::Number(json_number) = event {
1✔
1079
            assert_eq!(json_number.as_str(), "-123");
1✔
1080
        } else {
UNCOV
1081
            panic!("Expected Number event, got: {:?}", event);
×
1082
        }
1083

1084
        let event = parser.next_event().unwrap();
1✔
1085
        assert_eq!(event, Event::EndDocument);
1✔
1086
    }
1✔
1087

1088
    #[test]
1089
    fn test_direct_parser_number_float() {
1✔
1090
        let json = b"3.14159";
1✔
1091
        let reader = SliceReader::new(json);
1✔
1092
        let mut buffer = [0u8; 256];
1✔
1093
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1094

1095
        #[cfg(feature = "float-error")]
1096
        {
1097
            // float-error configuration should return an error for float values
1098
            let result = parser.next_event();
1099
            assert!(
1100
                result.is_err(),
1101
                "Expected error for float with float-error configuration"
1102
            );
1103
            return;
1104
        }
1105

1106
        #[cfg(not(feature = "float-error"))]
1107
        {
1108
            let event = parser.next_event().unwrap();
1✔
1109
            if let Event::Number(json_number) = event {
1✔
1110
                assert_eq!(json_number.as_str(), "3.14159");
1✔
1111
            } else {
UNCOV
1112
                panic!("Expected Number event, got: {:?}", event);
×
1113
            }
1114

1115
            let event = parser.next_event().unwrap();
1✔
1116
            assert_eq!(event, Event::EndDocument);
1✔
1117
        }
1118
    }
1✔
1119

1120
    #[test]
1121
    fn test_direct_parser_numbers_in_array() {
1✔
1122
        #[cfg(feature = "float-error")]
1123
        let json = b"[42, -7]"; // No floats for float-error config
1124
        #[cfg(not(feature = "float-error"))]
1125
        let json = b"[42, -7, 3.14]"; // Include float for other configs
1✔
1126

1127
        let reader = SliceReader::new(json);
1✔
1128
        let mut buffer = [0u8; 256];
1✔
1129
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1130

1131
        assert_eq!(parser.next_event().unwrap(), Event::StartArray);
1✔
1132

1133
        let event = parser.next_event().unwrap();
1✔
1134
        if let Event::Number(json_number) = event {
1✔
1135
            assert_eq!(json_number.as_str(), "42");
1✔
1136
        } else {
UNCOV
1137
            panic!("Expected Number event, got: {:?}", event);
×
1138
        }
1139

1140
        let event = parser.next_event().unwrap();
1✔
1141
        if let Event::Number(json_number) = event {
1✔
1142
            assert_eq!(json_number.as_str(), "-7");
1✔
1143
        } else {
UNCOV
1144
            panic!("Expected Number event, got: {:?}", event);
×
1145
        }
1146

1147
        #[cfg(not(feature = "float-error"))]
1148
        {
1149
            let event = parser.next_event().unwrap();
1✔
1150
            if let Event::Number(json_number) = event {
1✔
1151
                assert_eq!(json_number.as_str(), "3.14");
1✔
1152
            } else {
UNCOV
1153
                panic!("Expected Number event, got: {:?}", event);
×
1154
            }
1155
        }
1156

1157
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1✔
1158
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1159
    }
1✔
1160

1161
    #[test]
1162
    fn test_direct_parser_numbers_in_object() {
1✔
1163
        #[cfg(feature = "float-error")]
1164
        let json = b"{\"count\": 42, \"score\": -7}"; // No floats for float-error config
1165
        #[cfg(not(feature = "float-error"))]
1166
        let json = b"{\"count\": 42, \"score\": -7.5}"; // Include float for other configs
1✔
1167

1168
        let reader = SliceReader::new(json);
1✔
1169
        let mut buffer = [0u8; 256];
1✔
1170
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1171

1172
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1173

1174
        // First key-value pair
1175
        if let Event::Key(key1) = parser.next_event().unwrap() {
1✔
1176
            assert_eq!(key1.as_str(), "count");
1✔
1177
        } else {
UNCOV
1178
            panic!("Expected Key event");
×
1179
        }
1180

1181
        if let Event::Number(val1) = parser.next_event().unwrap() {
1✔
1182
            assert_eq!(val1.as_str(), "42");
1✔
1183
        } else {
UNCOV
1184
            panic!("Expected Number event");
×
1185
        }
1186

1187
        // Second key-value pair
1188
        if let Event::Key(key2) = parser.next_event().unwrap() {
1✔
1189
            assert_eq!(key2.as_str(), "score");
1✔
1190
        } else {
UNCOV
1191
            panic!("Expected Key event");
×
1192
        }
1193

1194
        if let Event::Number(val2) = parser.next_event().unwrap() {
1✔
1195
            #[cfg(feature = "float-error")]
1196
            assert_eq!(val2.as_str(), "-7");
1197
            #[cfg(not(feature = "float-error"))]
1198
            assert_eq!(val2.as_str(), "-7.5");
1✔
1199
        } else {
UNCOV
1200
            panic!("Expected Number event");
×
1201
        }
1202

1203
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1204
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1205
    }
1✔
1206

1207
    #[test]
1208
    fn test_direct_parser_no_float_configuration() {
1✔
1209
        // Test that StreamParser properly uses unified number parsing with no-float config
1210
        let json = br#"{"integer": 42, "float": 3.14, "scientific": 1e3}"#;
1✔
1211
        let reader = SliceReader::new(json);
1✔
1212
        let mut buffer = [0u8; 256];
1✔
1213
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1214

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

1218
        // Integer key-value
1219
        assert_eq!(
1✔
1220
            parser.next_event().unwrap(),
1✔
1221
            Event::Key(crate::String::Borrowed("integer"))
1222
        );
1223
        if let Event::Number(num) = parser.next_event().unwrap() {
1✔
1224
            assert_eq!(num.as_str(), "42");
1✔
1225
            match num.parsed() {
1✔
1226
                crate::NumberResult::Integer(i) => assert_eq!(*i, 42),
1✔
UNCOV
1227
                _ => panic!("Expected integer parsing"),
×
1228
            }
1229
        } else {
UNCOV
1230
            panic!("Expected Number event");
×
1231
        }
1232

1233
        // Float key-value - behavior varies by configuration
1234
        assert_eq!(
1✔
1235
            parser.next_event().unwrap(),
1✔
1236
            Event::Key(crate::String::Borrowed("float"))
1237
        );
1238

1239
        #[cfg(feature = "float-error")]
1240
        {
1241
            // float-error should return an error when encountering floats
1242
            let result = parser.next_event();
1243
            assert!(
1244
                result.is_err(),
1245
                "Expected error for float with float-error configuration"
1246
            );
1247
            // Test ends here for float-error - no more processing needed
1248
        }
1249

1250
        #[cfg(not(feature = "float-error"))]
1251
        {
1252
            if let Event::Number(num) = parser.next_event().unwrap() {
1✔
1253
                assert_eq!(num.as_str(), "3.14");
1✔
1254
                // In no-float configuration, this should be FloatDisabled
1255
                match num.parsed() {
1✔
1256
                    #[cfg(not(feature = "float"))]
1257
                    crate::NumberResult::FloatDisabled => {
1258
                        // This is expected in no-float build
1259
                    }
1260
                    #[cfg(feature = "float")]
1261
                    crate::NumberResult::Float(f) => {
1✔
1262
                        // This is expected in float-enabled build
1263
                        assert!((f - 3.14).abs() < 0.01);
1✔
1264
                    }
1265
                    #[cfg(feature = "float-skip")]
1266
                    crate::NumberResult::FloatSkipped => {
1267
                        // This is expected in float-skip build
1268
                    }
1269
                    #[cfg(feature = "float-truncate")]
1270
                    crate::NumberResult::FloatTruncated(i) => {
1271
                        // This is expected in float-truncate build (3.14 -> 3)
1272
                        assert_eq!(*i, 3);
1273
                    }
UNCOV
1274
                    _ => panic!("Unexpected number parsing result for float"),
×
1275
                }
1276
            } else {
UNCOV
1277
                panic!("Expected Number event");
×
1278
            }
1279

1280
            // Scientific notation handling varies by float configuration
1281
            assert_eq!(
1✔
1282
                parser.next_event().unwrap(),
1✔
1283
                Event::Key(crate::String::Borrowed("scientific"))
1284
            );
1285

1286
            // float-truncate rejects scientific notation, so test should end early for that config
1287
            #[cfg(feature = "float-truncate")]
1288
            {
1289
                // float-truncate rejects scientific notation since it would require float math
1290
                let result = parser.next_event();
1291
                assert!(
1292
                    result.is_err(),
1293
                    "Expected error for scientific notation with float-truncate"
1294
                );
1295
                // Test ends here for float-truncate - no more processing needed
1296
            }
1297

1298
            #[cfg(not(feature = "float-truncate"))]
1299
            {
1300
                if let Event::Number(num) = parser.next_event().unwrap() {
1✔
1301
                    assert_eq!(num.as_str(), "1e3");
1✔
1302
                    match num.parsed() {
1✔
1303
                        #[cfg(not(feature = "float"))]
1304
                        crate::NumberResult::FloatDisabled => {
1305
                            // This is expected in no-float build - raw string preserved for manual parsing
1306
                        }
1307
                        #[cfg(feature = "float-skip")]
1308
                        crate::NumberResult::FloatSkipped => {
1309
                            // This is expected in float-skip build
1310
                        }
1311
                        #[cfg(feature = "float")]
1312
                        crate::NumberResult::Float(f) => {
1✔
1313
                            // This is expected in float-enabled build
1314
                            assert!((f - 1000.0).abs() < f64::EPSILON);
1✔
1315
                        }
UNCOV
1316
                        _ => panic!("Unexpected number parsing result for scientific notation"),
×
1317
                    }
1318
                } else {
UNCOV
1319
                    panic!("Expected Number event");
×
1320
                }
1321

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

1328
    #[test]
1329
    fn test_number_parsing_delimiter_exclusion() {
1✔
1330
        // Test that numbers don't include trailing delimiters in various contexts
1331

1332
        // Test 1: Number followed by array end
1333
        let json1 = b"[123]";
1✔
1334
        let reader1 = SliceReader::new(json1);
1✔
1335
        let mut buffer1 = [0u8; 256];
1✔
1336
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
1337

1338
        assert!(matches!(parser1.next_event().unwrap(), Event::StartArray));
1✔
1339
        if let Event::Number(num) = parser1.next_event().unwrap() {
1✔
1340
            assert_eq!(
1✔
1341
                num.as_str(),
1✔
1342
                "123",
UNCOV
1343
                "Number should not include trailing delimiter ']'"
×
1344
            );
1345
        } else {
UNCOV
1346
            panic!("Expected Number event");
×
1347
        }
1348
        assert!(matches!(parser1.next_event().unwrap(), Event::EndArray));
1✔
1349

1350
        // Test 2: Number followed by object end
1351
        let json2 = b"{\"key\":456}";
1✔
1352
        let reader2 = SliceReader::new(json2);
1✔
1353
        let mut buffer2 = [0u8; 256];
1✔
1354
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
1355

1356
        assert!(matches!(parser2.next_event().unwrap(), Event::StartObject));
1✔
1357
        assert!(matches!(parser2.next_event().unwrap(), Event::Key(_)));
1✔
1358
        if let Event::Number(num) = parser2.next_event().unwrap() {
1✔
1359
            assert_eq!(
1✔
1360
                num.as_str(),
1✔
1361
                "456",
UNCOV
1362
                "Number should not include trailing delimiter '}}'"
×
1363
            );
1364
        } else {
UNCOV
1365
            panic!("Expected Number event");
×
1366
        }
1367
        assert!(matches!(parser2.next_event().unwrap(), Event::EndObject));
1✔
1368

1369
        // Test 3: Number followed by comma in array
1370
        let json3 = b"[789,10]";
1✔
1371
        let reader3 = SliceReader::new(json3);
1✔
1372
        let mut buffer3 = [0u8; 256];
1✔
1373
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
1374

1375
        assert!(matches!(parser3.next_event().unwrap(), Event::StartArray));
1✔
1376
        if let Event::Number(num1) = parser3.next_event().unwrap() {
1✔
1377
            assert_eq!(
1✔
1378
                num1.as_str(),
1✔
1379
                "789",
UNCOV
1380
                "First number should not include trailing delimiter ','"
×
1381
            );
1382
        } else {
UNCOV
1383
            panic!("Expected first Number event");
×
1384
        }
1385
        if let Event::Number(num2) = parser3.next_event().unwrap() {
1✔
1386
            assert_eq!(
1✔
1387
                num2.as_str(),
1✔
1388
                "10",
UNCOV
1389
                "Second number should not include trailing delimiter ']'"
×
1390
            );
1391
        } else {
UNCOV
1392
            panic!("Expected second Number event");
×
1393
        }
1394
        assert!(matches!(parser3.next_event().unwrap(), Event::EndArray));
1✔
1395

1396
        // Test 4: Number followed by comma in object
1397
        let json4 = b"{\"a\":11,\"b\":22}";
1✔
1398
        let reader4 = SliceReader::new(json4);
1✔
1399
        let mut buffer4 = [0u8; 256];
1✔
1400
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
1✔
1401

1402
        assert!(matches!(parser4.next_event().unwrap(), Event::StartObject));
1✔
1403
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1✔
1404
        if let Event::Number(num1) = parser4.next_event().unwrap() {
1✔
1405
            assert_eq!(
1✔
1406
                num1.as_str(),
1✔
1407
                "11",
UNCOV
1408
                "First number should not include trailing delimiter ','"
×
1409
            );
1410
        } else {
UNCOV
1411
            panic!("Expected first Number event");
×
1412
        }
1413
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1✔
1414
        if let Event::Number(num2) = parser4.next_event().unwrap() {
1✔
1415
            assert_eq!(
1✔
1416
                num2.as_str(),
1✔
1417
                "22",
UNCOV
1418
                "Second number should not include trailing delimiter '}}'"
×
1419
            );
1420
        } else {
UNCOV
1421
            panic!("Expected second Number event");
×
1422
        }
1423
        assert!(matches!(parser4.next_event().unwrap(), Event::EndObject));
1✔
1424

1425
        // Test 5: Standalone number at end of document (should include full content)
1426
        let json5 = b"999";
1✔
1427
        let reader5 = SliceReader::new(json5);
1✔
1428
        let mut buffer5 = [0u8; 256];
1✔
1429
        let mut parser5 = TestStreamParser::new(reader5, &mut buffer5);
1✔
1430

1431
        if let Event::Number(num) = parser5.next_event().unwrap() {
1✔
1432
            assert_eq!(
1✔
1433
                num.as_str(),
1✔
1434
                "999",
UNCOV
1435
                "Standalone number should include full content"
×
1436
            );
1437
        } else {
UNCOV
1438
            panic!("Expected Number event");
×
1439
        }
1440
        assert!(matches!(parser5.next_event().unwrap(), Event::EndDocument));
1✔
1441

1442
        // Test 6: Negative numbers with delimiters
1443
        let json6 = b"[-42,33]";
1✔
1444
        let reader6 = SliceReader::new(json6);
1✔
1445
        let mut buffer6 = [0u8; 256];
1✔
1446
        let mut parser6 = TestStreamParser::new(reader6, &mut buffer6);
1✔
1447

1448
        assert!(matches!(parser6.next_event().unwrap(), Event::StartArray));
1✔
1449
        if let Event::Number(num1) = parser6.next_event().unwrap() {
1✔
1450
            assert_eq!(
1✔
1451
                num1.as_str(),
1✔
1452
                "-42",
UNCOV
1453
                "Negative number should not include trailing delimiter ','"
×
1454
            );
1455
        } else {
UNCOV
1456
            panic!("Expected first Number event");
×
1457
        }
1458
        if let Event::Number(num2) = parser6.next_event().unwrap() {
1✔
1459
            assert_eq!(
1✔
1460
                num2.as_str(),
1✔
1461
                "33",
UNCOV
1462
                "Second number should not include trailing delimiter ']'"
×
1463
            );
1464
        } else {
UNCOV
1465
            panic!("Expected second Number event");
×
1466
        }
1467
        assert!(matches!(parser6.next_event().unwrap(), Event::EndArray));
1✔
1468

1469
        // Test 7: Decimal numbers with delimiters (if float enabled)
1470
        #[cfg(not(feature = "float-error"))]
1471
        {
1472
            let json7 = b"[3.14,2.71]";
1✔
1473
            let reader7 = SliceReader::new(json7);
1✔
1474
            let mut buffer7 = [0u8; 256];
1✔
1475
            let mut parser7 = TestStreamParser::new(reader7, &mut buffer7);
1✔
1476

1477
            assert!(matches!(parser7.next_event().unwrap(), Event::StartArray));
1✔
1478
            if let Event::Number(num1) = parser7.next_event().unwrap() {
1✔
1479
                assert_eq!(
1✔
1480
                    num1.as_str(),
1✔
1481
                    "3.14",
UNCOV
1482
                    "Decimal number should not include trailing delimiter ','"
×
1483
                );
1484
            } else {
UNCOV
1485
                panic!("Expected first Number event");
×
1486
            }
1487
            if let Event::Number(num2) = parser7.next_event().unwrap() {
1✔
1488
                assert_eq!(
1✔
1489
                    num2.as_str(),
1✔
1490
                    "2.71",
UNCOV
1491
                    "Second decimal number should not include trailing delimiter ']'"
×
1492
                );
1493
            } else {
UNCOV
1494
                panic!("Expected second Number event");
×
1495
            }
1496
            assert!(matches!(parser7.next_event().unwrap(), Event::EndArray));
1✔
1497
        }
1498
    }
1✔
1499

1500
    #[test]
1501
    fn test_escape_buffer_functions() {
1✔
1502
        // Test the uncovered escape processing functions
1503
        let json_stream = br#"{"escaped": "test\nstring"}"#;
1✔
1504
        let mut buffer = [0u8; 1024];
1✔
1505
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1✔
1506

1507
        // These functions are private but we can test them through the public API
1508
        // The escape processing should trigger the uncovered functions
1509
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1510
        assert_eq!(
1✔
1511
            parser.next_event().unwrap(),
1✔
1512
            Event::Key(crate::String::Borrowed("escaped"))
1513
        );
1514

1515
        // This should trigger append_byte_to_escape_buffer and queue_unescaped_reset
1516
        if let Event::String(s) = parser.next_event().unwrap() {
1✔
1517
            assert_eq!(s.as_ref(), "test\nstring"); // Escape sequence should be processed
1✔
1518
        } else {
UNCOV
1519
            panic!("Expected String event with escape sequence");
×
1520
        }
1521

1522
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1523
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1524
    }
1✔
1525

1526
    #[test]
1527
    fn test_slice_reader_constructor() {
1✔
1528
        // Test the uncovered SliceReader::new function
1529
        let data = b"test data";
1✔
1530
        let reader = SliceReader::new(data);
1✔
1531
        assert_eq!(reader.data, data);
1✔
1532
        assert_eq!(reader.position, 0);
1✔
1533
    }
1✔
1534

1535
    #[test]
1536
    fn test_complex_escape_sequences() {
1✔
1537
        // Test more complex escape processing to cover the escape buffer functions
1538
        let json_stream = br#"{"multi": "line1\nline2\ttab\r\n"}"#;
1✔
1539
        let mut buffer = [0u8; 1024];
1✔
1540
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1✔
1541

1542
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1543
        assert_eq!(
1✔
1544
            parser.next_event().unwrap(),
1✔
1545
            Event::Key(crate::String::Borrowed("multi"))
1546
        );
1547

1548
        // This should exercise the escape buffer processing extensively
1549
        if let Event::String(s) = parser.next_event().unwrap() {
1✔
1550
            assert_eq!(s.as_ref(), "line1\nline2\ttab\r\n");
1✔
1551
        } else {
UNCOV
1552
            panic!("Expected String event");
×
1553
        }
1554

1555
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1556
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1557
    }
1✔
1558
}
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