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

kaidokert / picojson-rs / 16082893332

05 Jul 2025 12:45AM UTC coverage: 94.432% (-0.1%) from 94.535%
16082893332

Pull #26

github

kaidokert
Fix panic handler
Pull Request #26: Panicfree

199 of 210 new or added lines in 11 files covered. (94.76%)

1 existing line in 1 file now uncovered.

2188 of 2317 relevant lines covered (94.43%)

132.92 hits per line

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

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

3
use crate::direct_buffer::DirectBuffer;
4
use crate::escape_processor::{EscapeProcessor, UnicodeEscapeCollector};
5
use crate::shared::{ContentRange, Event, ParseError, ParserErrorHandler, ParserState};
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
    /// DirectBuffer for single-buffer input and escape processing
52
    direct_buffer: DirectBuffer<'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
            direct_buffer: DirectBuffer::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.direct_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.direct_buffer.current_byte()?;
590✔
166
                    self.direct_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.direct_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.direct_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.direct_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.direct_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 DirectBuffer
344
    fn create_unescaped_string(&mut self) -> Result<Event<'_, '_>, ParseError> {
5✔
345
        self.queue_unescaped_reset();
5✔
346
        let unescaped_slice = self.direct_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 DirectBuffer
352
    fn create_borrowed_string(&mut self, start_pos: usize) -> Result<Event<'_, '_>, ParseError> {
6✔
353
        let current_pos = self.direct_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
            .direct_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.direct_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 DirectBuffer
380
    fn create_unescaped_key(&mut self) -> Result<Event<'_, '_>, ParseError> {
×
381
        self.queue_unescaped_reset();
×
382
        let unescaped_slice = self.direct_buffer.get_unescaped_slice()?;
×
NEW
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 DirectBuffer
388
    fn create_borrowed_key(&mut self, start_pos: usize) -> Result<Event<'_, '_>, ParseError> {
22✔
389
        let current_pos = self.direct_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
            .direct_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.direct_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.direct_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.direct_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.direct_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 DirectBuffer
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 DirectBuffer if not already started
476
        if !self.direct_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.direct_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
                    .direct_buffer
5✔
488
                    .remaining_bytes()
5✔
489
                    .wrapping_add(content_len);
5✔
490

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

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

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

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

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

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

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

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

555
        for &byte in &utf8_bytes_copy.0[..utf8_bytes_copy.1] {
3✔
556
            self.append_byte_to_escape_buffer(byte)?;
3✔
557
        }
558
        Ok(())
2✔
559
    }
2✔
560

561
    /// Append a byte to the DirectBuffer's unescaped content
562
    fn append_byte_to_escape_buffer(&mut self, byte: u8) -> Result<(), ParseError> {
44✔
563
        self.direct_buffer
44✔
564
            .append_unescaped_byte(byte)
44✔
565
            .map_err(|e| e.into())
44✔
566
    }
44✔
567

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

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

595
        if should_reset {
195✔
596
            self.direct_buffer.clear_unescaped();
2✔
597
        }
193✔
598
    }
195✔
599
}
600

601
impl<'b, R: Reader, C: BitStackConfig> PullParser for StreamParser<'b, R, C> {
602
    fn next_event(&mut self) -> Result<Event<'_, '_>, ParseError> {
195✔
603
        self.next_event_impl()
195✔
604
    }
195✔
605
}
606

607
#[cfg(test)]
608
mod tests {
609
    use super::*;
610
    use test_log::test;
611

612
    /// Simple test reader that reads from a byte slice
613
    pub struct SliceReader<'a> {
614
        data: &'a [u8],
615
        position: usize,
616
    }
617

618
    impl<'a> SliceReader<'a> {
619
        pub fn new(data: &'a [u8]) -> Self {
36✔
620
            Self { data, position: 0 }
36✔
621
        }
36✔
622
    }
623

624
    impl Reader for SliceReader<'_> {
625
        type Error = ();
626

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

633
            let to_copy = remaining.min(buf.len());
35✔
634
            buf[..to_copy]
35✔
635
                .copy_from_slice(&self.data[self.position..self.position.wrapping_add(to_copy)]);
35✔
636
            self.position = self.position.wrapping_add(to_copy);
35✔
637
            Ok(to_copy)
35✔
638
        }
576✔
639
    }
640

641
    type TestStreamParser<'b> = StreamParser<'b, SliceReader<'static>>;
642

643
    #[test]
644
    fn test_direct_parser_simple_object() {
645
        let json = b"{}";
646
        let reader = SliceReader::new(json);
647
        let mut buffer = [0u8; 256];
648
        let mut parser = TestStreamParser::new(reader, &mut buffer);
649

650
        // Should get ObjectStart
651
        let event = parser.next_event().unwrap();
652
        assert!(matches!(event, Event::StartObject));
653

654
        // Should get ObjectEnd
655
        let event = parser.next_event().unwrap();
656
        assert!(matches!(event, Event::EndObject));
657

658
        // Should get EndDocument
659
        let event = parser.next_event().unwrap();
660
        assert!(matches!(event, Event::EndDocument));
661
    }
662

663
    #[test]
664
    fn test_direct_parser_simple_array() {
665
        let json = b"[]";
666
        let reader = SliceReader::new(json);
667
        let mut buffer = [0u8; 256];
668
        let mut parser = TestStreamParser::new(reader, &mut buffer);
669

670
        // Should get ArrayStart
671
        let event = parser.next_event().unwrap();
672
        assert!(matches!(event, Event::StartArray));
673

674
        // Should get ArrayEnd
675
        let event = parser.next_event().unwrap();
676
        assert!(matches!(event, Event::EndArray));
677

678
        // Should get EndDocument
679
        let event = parser.next_event().unwrap();
680
        assert!(matches!(event, Event::EndDocument));
681
    }
682

683
    #[test]
684
    fn test_direct_parser_simple_escape() {
685
        let json = b"\"hello\\nworld\"";
686
        let reader = SliceReader::new(json);
687
        let mut buffer = [0u8; 256];
688
        let mut parser = TestStreamParser::new(reader, &mut buffer);
689

690
        if let Event::String(json_string) = parser.next_event().unwrap() {
691
            assert_eq!(json_string.as_str(), "hello\nworld");
692
        } else {
693
            panic!("Expected String event");
694
        }
695
    }
696

697
    #[test]
698
    fn test_pending_state_edge_cases() {
699
        // Test 1: Complex nested container endings
700
        let json1 = br#"{"a": {"b": [{"c": 123}]}}"#;
701
        let reader1 = SliceReader::new(json1);
702
        let mut buffer1 = [0u8; 256];
703
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
704

705
        let mut events = Vec::new();
706
        loop {
707
            match parser1.next_event() {
708
                Ok(Event::EndDocument) => break,
709
                Ok(event) => events.push(format!("{:?}", event)),
710
                Err(e) => panic!("Nested containers failed: {:?}", e),
711
            }
712
        }
713

714
        // Should contain all expected events
715
        assert!(events.len() >= 8); // StartObject, Key, StartObject, Key, StartArray, StartObject, Key, Number, EndObject, EndArray, EndObject, EndObject
716

717
        // Test 2: Mixed types after numbers in array
718
        let json2 = br#"[123, "string", true, null, 456]"#;
719
        let reader2 = SliceReader::new(json2);
720
        let mut buffer2 = [0u8; 256];
721
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
722

723
        let mut number_count = 0;
724
        loop {
725
            match parser2.next_event() {
726
                Ok(Event::EndDocument) => break,
727
                Ok(Event::Number(_)) => number_count += 1,
728
                Ok(_) => {}
729
                Err(e) => panic!("Mixed types failed: {:?}", e),
730
            }
731
        }
732
        assert_eq!(number_count, 2); // Should find both 123 and 456
733

734
        // Test 3: Empty containers
735
        let json3 = br#"[[], {}, [{}], {"empty": []}]"#;
736
        let reader3 = SliceReader::new(json3);
737
        let mut buffer3 = [0u8; 256];
738
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
739

740
        loop {
741
            match parser3.next_event() {
742
                Ok(Event::EndDocument) => break,
743
                Ok(_) => {}
744
                Err(e) => panic!("Empty containers failed: {:?}", e),
745
            }
746
        }
747

748
        // Test 4: Multiple consecutive numbers
749
        let json4 = br#"[1, 2, 3, 4, 5]"#;
750
        let reader4 = SliceReader::new(json4);
751
        let mut buffer4 = [0u8; 256];
752
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
753

754
        let mut consecutive_numbers = Vec::new();
755
        loop {
756
            match parser4.next_event() {
757
                Ok(Event::EndDocument) => break,
758
                Ok(Event::Number(n)) => consecutive_numbers.push(n.as_str().to_string()),
759
                Ok(_) => {}
760
                Err(e) => panic!("Consecutive numbers failed: {:?}", e),
761
            }
762
        }
763
        assert_eq!(consecutive_numbers, vec!["1", "2", "3", "4", "5"]);
764
    }
765

766
    #[test]
767
    fn test_error_recovery_with_pending_state() {
768
        // Test error handling - this should fail gracefully without hanging onto pending state
769
        let invalid_json = br#"{"key": 123,"#; // Missing closing brace
770
        let reader = SliceReader::new(invalid_json);
771
        let mut buffer = [0u8; 256];
772
        let mut parser = TestStreamParser::new(reader, &mut buffer);
773

774
        // Parse until we hit an error or EOF
775
        loop {
776
            match parser.next_event() {
777
                Ok(Event::EndDocument) => break, // EOF reached
778
                Ok(_) => {}
779
                Err(_) => break, // Error occurred - this is expected
780
            }
781
        }
782

783
        // The important thing is that we don't panic or hang
784
        // The specific error behavior may vary
785
    }
786

787
    #[test]
788
    fn test_multiple_rapid_container_ends() {
789
        // Test deeply nested structures that end with numbers
790
        // This tests whether we can handle multiple rapid container ends correctly
791

792
        // Test 1: Deeply nested arrays ending with number
793
        let json1 = br#"[[[123]]]"#;
794
        let reader1 = SliceReader::new(json1);
795
        let mut buffer1 = [0u8; 256];
796
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
797

798
        let mut events1 = Vec::new();
799
        loop {
800
            match parser1.next_event() {
801
                Ok(Event::EndDocument) => break,
802
                Ok(event) => events1.push(format!("{:?}", event)),
803
                Err(e) => panic!("Deeply nested arrays failed: {:?}", e),
804
            }
805
        }
806

807
        // Should have: StartArray, StartArray, StartArray, Number(123), EndArray, EndArray, EndArray
808
        assert_eq!(events1.len(), 7);
809
        assert!(events1[3].contains("Number"));
810
        assert_eq!(&events1[4], "EndArray");
811
        assert_eq!(&events1[5], "EndArray");
812
        assert_eq!(&events1[6], "EndArray");
813

814
        // Test 2: Mixed nested containers ending with number
815
        let json2 = br#"{"a": [{"b": 456}]}"#;
816
        let reader2 = SliceReader::new(json2);
817
        let mut buffer2 = [0u8; 256];
818
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
819

820
        let mut events2 = Vec::new();
821
        loop {
822
            match parser2.next_event() {
823
                Ok(Event::EndDocument) => break,
824
                Ok(event) => events2.push(format!("{:?}", event)),
825
                Err(e) => panic!("Mixed nested containers failed: {:?}", e),
826
            }
827
        }
828

829
        // Should properly handle the sequence of: number -> EndObject -> EndArray -> EndObject
830
        assert!(events2.len() >= 8);
831

832
        // Test 3: Multiple numbers at different nesting levels
833
        let json3 = br#"[123, [456, [789]]]"#;
834
        let reader3 = SliceReader::new(json3);
835
        let mut buffer3 = [0u8; 256];
836
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
837

838
        let mut number_count = 0;
839
        let mut events3 = Vec::new();
840
        loop {
841
            match parser3.next_event() {
842
                Ok(Event::EndDocument) => break,
843
                Ok(Event::Number(n)) => {
844
                    number_count += 1;
845
                    events3.push(format!("Number({})", n.as_str()));
846
                }
847
                Ok(event) => events3.push(format!("{:?}", event)),
848
                Err(e) => panic!("Multiple nested numbers failed: {:?}", e),
849
            }
850
        }
851

852
        assert_eq!(number_count, 3); // Should find all three numbers: 123, 456, 789
853
    }
854

855
    #[test]
856
    fn test_pending_flag_priority() {
857
        // Defensive test: ensure that if both pending flags were somehow set,
858
        // we handle it gracefully (this shouldn't happen in normal operation)
859

860
        let json = br#"[{"key": 123}]"#;
861
        let reader = SliceReader::new(json);
862
        let mut buffer = [0u8; 256];
863
        let mut parser = TestStreamParser::new(reader, &mut buffer);
864

865
        // Parse normally - this should work fine and never set both flags
866
        let mut events = Vec::new();
867
        loop {
868
            match parser.next_event() {
869
                Ok(Event::EndDocument) => break,
870
                Ok(event) => events.push(format!("{:?}", event)),
871
                Err(e) => panic!("Flag priority test failed: {:?}", e),
872
            }
873
        }
874

875
        // Should successfully parse: StartArray, StartObject, Key, Number, EndObject, EndArray
876
        assert_eq!(events.len(), 6);
877
        assert!(events[3].contains("Number"));
878
        assert_eq!(&events[4], "EndObject");
879
        assert_eq!(&events[5], "EndArray");
880
    }
881

882
    #[test]
883
    fn test_direct_parser_array_of_strings() {
884
        let json = b"[\"first\", \"second\"]";
885
        let reader = SliceReader::new(json);
886
        let mut buffer = [0u8; 256];
887
        let mut parser = TestStreamParser::new(reader, &mut buffer);
888

889
        assert!(matches!(parser.next_event().unwrap(), Event::StartArray));
890

891
        if let Event::String(s1) = parser.next_event().unwrap() {
892
            assert_eq!(s1.as_str(), "first");
893
        } else {
894
            panic!("Expected String event");
895
        }
896

897
        if let Event::String(s2) = parser.next_event().unwrap() {
898
            assert_eq!(s2.as_str(), "second");
899
        } else {
900
            panic!("Expected String event");
901
        }
902

903
        assert!(matches!(parser.next_event().unwrap(), Event::EndArray));
904
    }
905

906
    #[test]
907
    fn test_direct_parser_object_with_keys() {
908
        let json = b"{\"name\": \"value\", \"count\": \"42\"}";
909
        let reader = SliceReader::new(json);
910
        let mut buffer = [0u8; 256];
911
        let mut parser = TestStreamParser::new(reader, &mut buffer);
912

913
        assert!(matches!(parser.next_event().unwrap(), Event::StartObject));
914

915
        // First key-value pair
916
        if let Event::Key(key1) = parser.next_event().unwrap() {
917
            assert_eq!(key1.as_str(), "name");
918
        } else {
919
            panic!("Expected Key event");
920
        }
921

922
        if let Event::String(val1) = parser.next_event().unwrap() {
923
            assert_eq!(val1.as_str(), "value");
924
        } else {
925
            panic!("Expected String event");
926
        }
927

928
        // Second key-value pair
929
        if let Event::Key(key2) = parser.next_event().unwrap() {
930
            assert_eq!(key2.as_str(), "count");
931
        } else {
932
            panic!("Expected Key event");
933
        }
934

935
        if let Event::String(val2) = parser.next_event().unwrap() {
936
            assert_eq!(val2.as_str(), "42");
937
        } else {
938
            panic!("Expected String event");
939
        }
940

941
        assert!(matches!(parser.next_event().unwrap(), Event::EndObject));
942
    }
943

944
    #[test]
945
    fn test_direct_parser_multiple_escapes() {
946
        let json = b"\"line1\\nline2\\ttab\\\"quote\"";
947
        let reader = SliceReader::new(json);
948
        let mut buffer = [0u8; 256];
949
        let mut parser = TestStreamParser::new(reader, &mut buffer);
950

951
        if let Event::String(json_string) = parser.next_event().unwrap() {
952
            let content = json_string.as_str();
953
            // Check that escape sequences were properly processed
954
            let has_newline = content.contains('\n');
955
            let has_tab = content.contains('\t');
956
            let has_quote = content.contains('"');
957

958
            // These should be real control characters, not literal \n \t \"
959
            assert!(has_newline, "Should contain actual newline character");
960
            assert!(has_tab, "Should contain actual tab character");
961
            assert!(has_quote, "Should contain actual quote character");
962
        } else {
963
            panic!("Expected String event");
964
        }
965
    }
966

967
    #[test]
968
    fn test_direct_parser_unicode_escape() {
969
        let json = b"\"Hello \\u0041\\u03B1\""; // Hello A(alpha)
970
        let reader = SliceReader::new(json);
971
        let mut buffer = [0u8; 256];
972
        let mut parser = TestStreamParser::new(reader, &mut buffer);
973

974
        if let Event::String(json_string) = parser.next_event().unwrap() {
975
            let content = json_string.as_str();
976
            // Should be "Hello A⍺" (with actual A and alpha characters)
977
            assert!(content.contains('A'));
978
            // Note: This test will initially fail until we implement Unicode escapes
979
        } else {
980
            panic!("Expected String event");
981
        }
982
    }
983

984
    #[test]
985
    fn test_direct_parser_boolean_true() {
986
        let json = b"true";
987
        let reader = SliceReader::new(json);
988
        let mut buffer = [0u8; 256];
989
        let mut parser = TestStreamParser::new(reader, &mut buffer);
990

991
        let event = parser.next_event().unwrap();
992
        assert_eq!(event, Event::Bool(true));
993

994
        let event = parser.next_event().unwrap();
995
        assert_eq!(event, Event::EndDocument);
996
    }
997

998
    #[test]
999
    fn test_direct_parser_boolean_false() {
1000
        let json = b"false";
1001
        let reader = SliceReader::new(json);
1002
        let mut buffer = [0u8; 256];
1003
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1004

1005
        let event = parser.next_event().unwrap();
1006
        assert_eq!(event, Event::Bool(false));
1007

1008
        let event = parser.next_event().unwrap();
1009
        assert_eq!(event, Event::EndDocument);
1010
    }
1011

1012
    #[test]
1013
    fn test_direct_parser_null() {
1014
        let json = b"null";
1015
        let reader = SliceReader::new(json);
1016
        let mut buffer = [0u8; 256];
1017
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1018

1019
        let event = parser.next_event().unwrap();
1020
        assert_eq!(event, Event::Null);
1021

1022
        let event = parser.next_event().unwrap();
1023
        assert_eq!(event, Event::EndDocument);
1024
    }
1025

1026
    #[test]
1027
    fn test_direct_parser_booleans_in_array() {
1028
        let json = b"[true, false, null]";
1029
        let reader = SliceReader::new(json);
1030
        let mut buffer = [0u8; 256];
1031
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1032

1033
        assert_eq!(parser.next_event().unwrap(), Event::StartArray);
1034
        assert_eq!(parser.next_event().unwrap(), Event::Bool(true));
1035
        assert_eq!(parser.next_event().unwrap(), Event::Bool(false));
1036
        assert_eq!(parser.next_event().unwrap(), Event::Null);
1037
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1038
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1039
    }
1040

1041
    #[test_log::test]
1042
    fn test_direct_parser_number_simple() {
1043
        let json = b"42";
1044
        let reader = SliceReader::new(json);
1045
        let mut buffer = [0u8; 256];
1046
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1047

1048
        let event = parser.next_event().unwrap();
1049
        if let Event::Number(json_number) = event {
1050
            assert_eq!(json_number.as_str(), "42");
1051
        } else {
1052
            panic!("Expected Number event, got: {:?}", event);
1053
        }
1054

1055
        let event = parser.next_event().unwrap();
1056
        assert_eq!(event, Event::EndDocument);
1057
    }
1058

1059
    #[test]
1060
    fn test_direct_parser_number_negative() {
1061
        let json = b"-123";
1062
        let reader = SliceReader::new(json);
1063
        let mut buffer = [0u8; 256];
1064
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1065

1066
        let event = parser.next_event().unwrap();
1067
        if let Event::Number(json_number) = event {
1068
            assert_eq!(json_number.as_str(), "-123");
1069
        } else {
1070
            panic!("Expected Number event, got: {:?}", event);
1071
        }
1072

1073
        let event = parser.next_event().unwrap();
1074
        assert_eq!(event, Event::EndDocument);
1075
    }
1076

1077
    #[test]
1078
    fn test_direct_parser_number_float() {
1079
        let json = b"3.14159";
1080
        let reader = SliceReader::new(json);
1081
        let mut buffer = [0u8; 256];
1082
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1083

1084
        #[cfg(feature = "float-error")]
1085
        {
1086
            // float-error configuration should return an error for float values
1087
            let result = parser.next_event();
1088
            assert!(
1089
                result.is_err(),
1090
                "Expected error for float with float-error configuration"
1091
            );
1092
            return;
1093
        }
1094

1095
        #[cfg(not(feature = "float-error"))]
1096
        {
1097
            let event = parser.next_event().unwrap();
1098
            if let Event::Number(json_number) = event {
1099
                assert_eq!(json_number.as_str(), "3.14159");
1100
            } else {
1101
                panic!("Expected Number event, got: {:?}", event);
1102
            }
1103

1104
            let event = parser.next_event().unwrap();
1105
            assert_eq!(event, Event::EndDocument);
1106
        }
1107
    }
1108

1109
    #[test_log::test]
1110
    fn test_direct_parser_numbers_in_array() {
1111
        #[cfg(feature = "float-error")]
1112
        let json = b"[42, -7]"; // No floats for float-error config
1113
        #[cfg(not(feature = "float-error"))]
1114
        let json = b"[42, -7, 3.14]"; // Include float for other configs
1115

1116
        let reader = SliceReader::new(json);
1117
        let mut buffer = [0u8; 256];
1118
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1119

1120
        assert_eq!(parser.next_event().unwrap(), Event::StartArray);
1121

1122
        let event = parser.next_event().unwrap();
1123
        if let Event::Number(json_number) = event {
1124
            assert_eq!(json_number.as_str(), "42");
1125
        } else {
1126
            panic!("Expected Number event, got: {:?}", event);
1127
        }
1128

1129
        let event = parser.next_event().unwrap();
1130
        if let Event::Number(json_number) = event {
1131
            assert_eq!(json_number.as_str(), "-7");
1132
        } else {
1133
            panic!("Expected Number event, got: {:?}", event);
1134
        }
1135

1136
        #[cfg(not(feature = "float-error"))]
1137
        {
1138
            let event = parser.next_event().unwrap();
1139
            if let Event::Number(json_number) = event {
1140
                assert_eq!(json_number.as_str(), "3.14");
1141
            } else {
1142
                panic!("Expected Number event, got: {:?}", event);
1143
            }
1144
        }
1145

1146
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1147
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1148
    }
1149

1150
    #[test_log::test]
1151
    fn test_direct_parser_numbers_in_object() {
1152
        #[cfg(feature = "float-error")]
1153
        let json = b"{\"count\": 42, \"score\": -7}"; // No floats for float-error config
1154
        #[cfg(not(feature = "float-error"))]
1155
        let json = b"{\"count\": 42, \"score\": -7.5}"; // Include float for other configs
1156

1157
        let reader = SliceReader::new(json);
1158
        let mut buffer = [0u8; 256];
1159
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1160

1161
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1162

1163
        // First key-value pair
1164
        if let Event::Key(key1) = parser.next_event().unwrap() {
1165
            assert_eq!(key1.as_str(), "count");
1166
        } else {
1167
            panic!("Expected Key event");
1168
        }
1169

1170
        if let Event::Number(val1) = parser.next_event().unwrap() {
1171
            assert_eq!(val1.as_str(), "42");
1172
        } else {
1173
            panic!("Expected Number event");
1174
        }
1175

1176
        // Second key-value pair
1177
        if let Event::Key(key2) = parser.next_event().unwrap() {
1178
            assert_eq!(key2.as_str(), "score");
1179
        } else {
1180
            panic!("Expected Key event");
1181
        }
1182

1183
        if let Event::Number(val2) = parser.next_event().unwrap() {
1184
            #[cfg(feature = "float-error")]
1185
            assert_eq!(val2.as_str(), "-7");
1186
            #[cfg(not(feature = "float-error"))]
1187
            assert_eq!(val2.as_str(), "-7.5");
1188
        } else {
1189
            panic!("Expected Number event");
1190
        }
1191

1192
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1193
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1194
    }
1195

1196
    #[test]
1197
    fn test_direct_parser_no_float_configuration() {
1198
        // Test that StreamParser properly uses unified number parsing with no-float config
1199
        let json = br#"{"integer": 42, "float": 3.14, "scientific": 1e3}"#;
1200
        let reader = SliceReader::new(json);
1201
        let mut buffer = [0u8; 256];
1202
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1203

1204
        // Parse through the JSON and verify number handling
1205
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1206

1207
        // Integer key-value
1208
        assert_eq!(
1209
            parser.next_event().unwrap(),
1210
            Event::Key(crate::String::Borrowed("integer"))
1211
        );
1212
        if let Event::Number(num) = parser.next_event().unwrap() {
1213
            assert_eq!(num.as_str(), "42");
1214
            match num.parsed() {
1215
                crate::NumberResult::Integer(i) => assert_eq!(*i, 42),
1216
                _ => panic!("Expected integer parsing"),
1217
            }
1218
        } else {
1219
            panic!("Expected Number event");
1220
        }
1221

1222
        // Float key-value - behavior varies by configuration
1223
        assert_eq!(
1224
            parser.next_event().unwrap(),
1225
            Event::Key(crate::String::Borrowed("float"))
1226
        );
1227

1228
        #[cfg(feature = "float-error")]
1229
        {
1230
            // float-error should return an error when encountering floats
1231
            let result = parser.next_event();
1232
            assert!(
1233
                result.is_err(),
1234
                "Expected error for float with float-error configuration"
1235
            );
1236
            // Test ends here for float-error - no more processing needed
1237
        }
1238

1239
        #[cfg(not(feature = "float-error"))]
1240
        {
1241
            if let Event::Number(num) = parser.next_event().unwrap() {
1242
                assert_eq!(num.as_str(), "3.14");
1243
                // In no-float configuration, this should be FloatDisabled
1244
                match num.parsed() {
1245
                    #[cfg(not(feature = "float"))]
1246
                    crate::NumberResult::FloatDisabled => {
1247
                        // This is expected in no-float build
1248
                    }
1249
                    #[cfg(feature = "float")]
1250
                    crate::NumberResult::Float(f) => {
1251
                        // This is expected in float-enabled build
1252
                        assert!((f - 3.14).abs() < 0.01);
1253
                    }
1254
                    #[cfg(feature = "float-skip")]
1255
                    crate::NumberResult::FloatSkipped => {
1256
                        // This is expected in float-skip build
1257
                    }
1258
                    #[cfg(feature = "float-truncate")]
1259
                    crate::NumberResult::FloatTruncated(i) => {
1260
                        // This is expected in float-truncate build (3.14 -> 3)
1261
                        assert_eq!(*i, 3);
1262
                    }
1263
                    _ => panic!("Unexpected number parsing result for float"),
1264
                }
1265
            } else {
1266
                panic!("Expected Number event");
1267
            }
1268

1269
            // Scientific notation handling varies by float configuration
1270
            assert_eq!(
1271
                parser.next_event().unwrap(),
1272
                Event::Key(crate::String::Borrowed("scientific"))
1273
            );
1274

1275
            // float-truncate rejects scientific notation, so test should end early for that config
1276
            #[cfg(feature = "float-truncate")]
1277
            {
1278
                // float-truncate rejects scientific notation since it would require float math
1279
                let result = parser.next_event();
1280
                assert!(
1281
                    result.is_err(),
1282
                    "Expected error for scientific notation with float-truncate"
1283
                );
1284
                // Test ends here for float-truncate - no more processing needed
1285
            }
1286

1287
            #[cfg(not(feature = "float-truncate"))]
1288
            {
1289
                if let Event::Number(num) = parser.next_event().unwrap() {
1290
                    assert_eq!(num.as_str(), "1e3");
1291
                    match num.parsed() {
1292
                        #[cfg(not(feature = "float"))]
1293
                        crate::NumberResult::FloatDisabled => {
1294
                            // This is expected in no-float build - raw string preserved for manual parsing
1295
                        }
1296
                        #[cfg(feature = "float-skip")]
1297
                        crate::NumberResult::FloatSkipped => {
1298
                            // This is expected in float-skip build
1299
                        }
1300
                        #[cfg(feature = "float")]
1301
                        crate::NumberResult::Float(f) => {
1302
                            // This is expected in float-enabled build
1303
                            assert!((f - 1000.0).abs() < f64::EPSILON);
1304
                        }
1305
                        _ => panic!("Unexpected number parsing result for scientific notation"),
1306
                    }
1307
                } else {
1308
                    panic!("Expected Number event");
1309
                }
1310

1311
                assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1312
                assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1313
            }
1314
        }
1315
    }
1316

1317
    #[test]
1318
    fn test_number_parsing_delimiter_exclusion() {
1319
        // Test that numbers don't include trailing delimiters in various contexts
1320

1321
        // Test 1: Number followed by array end
1322
        let json1 = b"[123]";
1323
        let reader1 = SliceReader::new(json1);
1324
        let mut buffer1 = [0u8; 256];
1325
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1326

1327
        assert!(matches!(parser1.next_event().unwrap(), Event::StartArray));
1328
        if let Event::Number(num) = parser1.next_event().unwrap() {
1329
            assert_eq!(
1330
                num.as_str(),
1331
                "123",
1332
                "Number should not include trailing delimiter ']'"
1333
            );
1334
        } else {
1335
            panic!("Expected Number event");
1336
        }
1337
        assert!(matches!(parser1.next_event().unwrap(), Event::EndArray));
1338

1339
        // Test 2: Number followed by object end
1340
        let json2 = b"{\"key\":456}";
1341
        let reader2 = SliceReader::new(json2);
1342
        let mut buffer2 = [0u8; 256];
1343
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1344

1345
        assert!(matches!(parser2.next_event().unwrap(), Event::StartObject));
1346
        assert!(matches!(parser2.next_event().unwrap(), Event::Key(_)));
1347
        if let Event::Number(num) = parser2.next_event().unwrap() {
1348
            assert_eq!(
1349
                num.as_str(),
1350
                "456",
1351
                "Number should not include trailing delimiter '}}'"
1352
            );
1353
        } else {
1354
            panic!("Expected Number event");
1355
        }
1356
        assert!(matches!(parser2.next_event().unwrap(), Event::EndObject));
1357

1358
        // Test 3: Number followed by comma in array
1359
        let json3 = b"[789,10]";
1360
        let reader3 = SliceReader::new(json3);
1361
        let mut buffer3 = [0u8; 256];
1362
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1363

1364
        assert!(matches!(parser3.next_event().unwrap(), Event::StartArray));
1365
        if let Event::Number(num1) = parser3.next_event().unwrap() {
1366
            assert_eq!(
1367
                num1.as_str(),
1368
                "789",
1369
                "First number should not include trailing delimiter ','"
1370
            );
1371
        } else {
1372
            panic!("Expected first Number event");
1373
        }
1374
        if let Event::Number(num2) = parser3.next_event().unwrap() {
1375
            assert_eq!(
1376
                num2.as_str(),
1377
                "10",
1378
                "Second number should not include trailing delimiter ']'"
1379
            );
1380
        } else {
1381
            panic!("Expected second Number event");
1382
        }
1383
        assert!(matches!(parser3.next_event().unwrap(), Event::EndArray));
1384

1385
        // Test 4: Number followed by comma in object
1386
        let json4 = b"{\"a\":11,\"b\":22}";
1387
        let reader4 = SliceReader::new(json4);
1388
        let mut buffer4 = [0u8; 256];
1389
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
1390

1391
        assert!(matches!(parser4.next_event().unwrap(), Event::StartObject));
1392
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1393
        if let Event::Number(num1) = parser4.next_event().unwrap() {
1394
            assert_eq!(
1395
                num1.as_str(),
1396
                "11",
1397
                "First number should not include trailing delimiter ','"
1398
            );
1399
        } else {
1400
            panic!("Expected first Number event");
1401
        }
1402
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1403
        if let Event::Number(num2) = parser4.next_event().unwrap() {
1404
            assert_eq!(
1405
                num2.as_str(),
1406
                "22",
1407
                "Second number should not include trailing delimiter '}}'"
1408
            );
1409
        } else {
1410
            panic!("Expected second Number event");
1411
        }
1412
        assert!(matches!(parser4.next_event().unwrap(), Event::EndObject));
1413

1414
        // Test 5: Standalone number at end of document (should include full content)
1415
        let json5 = b"999";
1416
        let reader5 = SliceReader::new(json5);
1417
        let mut buffer5 = [0u8; 256];
1418
        let mut parser5 = TestStreamParser::new(reader5, &mut buffer5);
1419

1420
        if let Event::Number(num) = parser5.next_event().unwrap() {
1421
            assert_eq!(
1422
                num.as_str(),
1423
                "999",
1424
                "Standalone number should include full content"
1425
            );
1426
        } else {
1427
            panic!("Expected Number event");
1428
        }
1429
        assert!(matches!(parser5.next_event().unwrap(), Event::EndDocument));
1430

1431
        // Test 6: Negative numbers with delimiters
1432
        let json6 = b"[-42,33]";
1433
        let reader6 = SliceReader::new(json6);
1434
        let mut buffer6 = [0u8; 256];
1435
        let mut parser6 = TestStreamParser::new(reader6, &mut buffer6);
1436

1437
        assert!(matches!(parser6.next_event().unwrap(), Event::StartArray));
1438
        if let Event::Number(num1) = parser6.next_event().unwrap() {
1439
            assert_eq!(
1440
                num1.as_str(),
1441
                "-42",
1442
                "Negative number should not include trailing delimiter ','"
1443
            );
1444
        } else {
1445
            panic!("Expected first Number event");
1446
        }
1447
        if let Event::Number(num2) = parser6.next_event().unwrap() {
1448
            assert_eq!(
1449
                num2.as_str(),
1450
                "33",
1451
                "Second number should not include trailing delimiter ']'"
1452
            );
1453
        } else {
1454
            panic!("Expected second Number event");
1455
        }
1456
        assert!(matches!(parser6.next_event().unwrap(), Event::EndArray));
1457

1458
        // Test 7: Decimal numbers with delimiters (if float enabled)
1459
        #[cfg(not(feature = "float-error"))]
1460
        {
1461
            let json7 = b"[3.14,2.71]";
1462
            let reader7 = SliceReader::new(json7);
1463
            let mut buffer7 = [0u8; 256];
1464
            let mut parser7 = TestStreamParser::new(reader7, &mut buffer7);
1465

1466
            assert!(matches!(parser7.next_event().unwrap(), Event::StartArray));
1467
            if let Event::Number(num1) = parser7.next_event().unwrap() {
1468
                assert_eq!(
1469
                    num1.as_str(),
1470
                    "3.14",
1471
                    "Decimal number should not include trailing delimiter ','"
1472
                );
1473
            } else {
1474
                panic!("Expected first Number event");
1475
            }
1476
            if let Event::Number(num2) = parser7.next_event().unwrap() {
1477
                assert_eq!(
1478
                    num2.as_str(),
1479
                    "2.71",
1480
                    "Second decimal number should not include trailing delimiter ']'"
1481
                );
1482
            } else {
1483
                panic!("Expected second Number event");
1484
            }
1485
            assert!(matches!(parser7.next_event().unwrap(), Event::EndArray));
1486
        }
1487
    }
1488

1489
    #[test]
1490
    fn test_escape_buffer_functions() {
1491
        // Test the uncovered escape processing functions
1492
        let json_stream = br#"{"escaped": "test\nstring"}"#;
1493
        let mut buffer = [0u8; 1024];
1494
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1495

1496
        // These functions are private but we can test them through the public API
1497
        // The escape processing should trigger the uncovered functions
1498
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1499
        assert_eq!(
1500
            parser.next_event().unwrap(),
1501
            Event::Key(crate::String::Borrowed("escaped"))
1502
        );
1503

1504
        // This should trigger append_byte_to_escape_buffer and queue_unescaped_reset
1505
        if let Event::String(s) = parser.next_event().unwrap() {
1506
            assert_eq!(s.as_ref(), "test\nstring"); // Escape sequence should be processed
1507
        } else {
1508
            panic!("Expected String event with escape sequence");
1509
        }
1510

1511
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1512
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1513
    }
1514

1515
    #[test]
1516
    fn test_slice_reader_constructor() {
1517
        // Test the uncovered SliceReader::new function
1518
        let data = b"test data";
1519
        let reader = SliceReader::new(data);
1520
        assert_eq!(reader.data, data);
1521
        assert_eq!(reader.position, 0);
1522
    }
1523

1524
    #[test]
1525
    fn test_complex_escape_sequences() {
1526
        // Test more complex escape processing to cover the escape buffer functions
1527
        let json_stream = br#"{"multi": "line1\nline2\ttab\r\n"}"#;
1528
        let mut buffer = [0u8; 1024];
1529
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1530

1531
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1532
        assert_eq!(
1533
            parser.next_event().unwrap(),
1534
            Event::Key(crate::String::Borrowed("multi"))
1535
        );
1536

1537
        // This should exercise the escape buffer processing extensively
1538
        if let Event::String(s) = parser.next_event().unwrap() {
1539
            assert_eq!(s.as_ref(), "line1\nline2\ttab\r\n");
1540
        } else {
1541
            panic!("Expected String event");
1542
        }
1543

1544
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1545
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1546
    }
1547
}
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