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

kaidokert / picojson-rs / 16259755145

14 Jul 2025 06:34AM UTC coverage: 90.098% (-3.7%) from 93.785%
16259755145

Pull #56

github

web-flow
Merge 9f3cfb7e4 into 6be34a4b2
Pull Request #56: Another big refactor

454 of 677 new or added lines in 9 files covered. (67.06%)

11 existing lines in 3 files now uncovered.

4786 of 5312 relevant lines covered (90.1%)

723.48 hits per line

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

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

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

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

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

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

27
/// A pull parser that parses JSON from a stream.
28
///
29
/// Generic over BitStackConfig for configurable nesting depth.
30
/// It is designed to be used with the [Reader] trait, which is used to read data from a stream.
31
///
32
pub struct StreamParser<'b, R: Reader, C: BitStackConfig = DefaultConfig> {
33
    /// The shared parser core that handles the unified event processing loop
34
    parser_core: ParserCore<C::Bucket, C::Counter>,
35
    /// The content builder that handles StreamParser-specific content extraction
36
    content_builder: StreamContentBuilder<'b>,
37
    /// Reader for streaming input
38
    reader: R,
39
    /// Flag to track if input is finished
40
    finished: bool,
41
}
42

43
/// Methods for StreamParser using DefaultConfig
44
impl<'b, R: Reader> StreamParser<'b, R, DefaultConfig> {
45
    /// Create a new StreamParser with default configuration
46
    ///
47
    /// Uses the default BitStack configuration (u32 bucket, u8 counter)
48
    /// for most common use cases.
49
    pub fn new(reader: R, buffer: &'b mut [u8]) -> Self {
1,040✔
50
        Self::with_config(reader, buffer)
1,040✔
51
    }
1,040✔
52
}
53

54
/// Methods for StreamParser with custom BitStackConfig
55
impl<'b, R: Reader, C: BitStackConfig> StreamParser<'b, R, C> {
56
    /// Create a new StreamParser with custom configuration
57
    ///
58
    /// Use this when you need custom BitStack storage types for specific
59
    /// memory or nesting depth requirements.
60
    ///
61
    /// # Example
62
    /// ```
63
    /// use picojson::{StreamParser, BitStackStruct, ChunkReader};
64
    ///
65
    /// let json = b"{\"test\": 42}";
66
    /// // For testing, ChunkReader is a convenient Reader implementation
67
    /// let reader = ChunkReader::new(json, 10);
68
    /// let mut buffer = [0u8; 256];
69
    ///
70
    /// // Custom configuration: u64 bucket + u16 counter for deeper nesting
71
    /// let mut parser = StreamParser::<_, BitStackStruct<u64, u16>>::with_config(reader, &mut buffer);
72
    /// ```
73
    pub fn with_config(reader: R, buffer: &'b mut [u8]) -> Self {
1,082✔
74
        Self {
1,082✔
75
            parser_core: ParserCore::new(),
1,082✔
76
            content_builder: StreamContentBuilder::new(buffer),
1,082✔
77
            reader,
1,082✔
78
            finished: false,
1,082✔
79
        }
1,082✔
80
    }
1,082✔
81
}
82

83
/// Shared methods for StreamParser with any BitStackConfig
84
impl<R: Reader, C: BitStackConfig> StreamParser<'_, R, C> {
85
    /// Get the next JSON event from the stream
86
    fn next_event_impl(&mut self) -> Result<Event<'_, '_>, ParseError> {
4,968✔
87
        // We need to implement the unified loop locally to avoid borrowing conflicts
88
        // This is essentially a copy of ParserCore::next_event_impl but accessing fields directly
89
        loop {
90
            while !crate::event_processor::have_events(&self.parser_core.parser_state.evts) {
27,345✔
91
                if let Some(byte) = self.next_byte()? {
19,365✔
92
                    let pos_before = self.content_builder.current_position();
18,336✔
93
                    log::trace!(
18,336✔
NEW
94
                        "[NEW] Processing byte '{}' ({}) at pos {}",
×
NEW
95
                        byte as char,
×
96
                        byte,
97
                        pos_before
98
                    );
99

100
                    crate::event_processor::process_byte_through_tokenizer(
18,336✔
101
                        byte,
18,336✔
102
                        &mut self.parser_core.tokenizer,
18,336✔
103
                        &mut self.parser_core.parser_state.evts,
18,336✔
NEW
104
                    )?;
×
105

106
                    let has_events =
18,336✔
107
                        crate::event_processor::have_events(&self.parser_core.parser_state.evts);
18,336✔
108
                    log::trace!("[NEW] After tokenizer: has_events={}", has_events);
18,336✔
109

110
                    // Handle byte accumulation if no event was generated (StreamParser-specific)
111
                    if !has_events {
18,336✔
112
                        log::trace!("[NEW] No events generated, calling handle_byte_accumulation");
11,249✔
113
                        self.handle_byte_accumulation(byte)?;
11,249✔
114
                    }
7,087✔
115
                } else {
116
                    // Handle end of data with tokenizer finish
117
                    if !self.finished {
500✔
118
                        self.finished = true;
496✔
119
                        crate::event_processor::finish_tokenizer(
496✔
120
                            &mut self.parser_core.tokenizer,
496✔
121
                            &mut self.parser_core.parser_state.evts,
496✔
122
                        )?;
1✔
123
                    }
4✔
124

125
                    if !crate::event_processor::have_events(&self.parser_core.parser_state.evts) {
499✔
126
                        return Ok(Event::EndDocument);
493✔
127
                    }
6✔
128
                }
129
            }
130

131
            let taken_event =
7,980✔
132
                crate::event_processor::take_first_event(&mut self.parser_core.parser_state.evts);
7,980✔
133
            let Some(taken) = taken_event else {
7,980✔
134
                return Err(crate::shared::UnexpectedState::StateMismatch.into());
×
135
            };
136

137
            // Try shared event processors first
138
            if let Some(result) =
5,379✔
139
                crate::event_processor::process_simple_events(&taken).or_else(|| {
7,980✔
140
                    crate::event_processor::process_begin_events(&taken, &mut self.content_builder)
4,051✔
141
                })
4,051✔
142
            {
143
                match result {
5,379✔
144
                    crate::event_processor::EventResult::Complete(event) => return Ok(event),
3,035✔
145
                    crate::event_processor::EventResult::ExtractString => {
146
                        return self.content_builder.validate_and_extract_string()
386✔
147
                    }
148
                    crate::event_processor::EventResult::ExtractKey => {
149
                        return self.content_builder.validate_and_extract_key()
255✔
150
                    }
151
                    crate::event_processor::EventResult::ExtractNumber(from_container_end) => {
253✔
152
                        return self.extract_number_with_finished_state(from_container_end)
253✔
153
                    }
154
                    crate::event_processor::EventResult::Continue => continue,
1,450✔
155
                }
156
            }
2,601✔
157

158
            // Handle parser-specific events (StreamParser uses OnEnd timing)
159
            match taken {
674✔
160
                ujson::Event::Begin(crate::ujson::EventToken::EscapeSequence) => {
161
                    crate::event_processor::process_begin_escape_sequence_event(
901✔
162
                        &mut self.content_builder,
901✔
NEW
163
                    )?;
×
164
                }
165
                _ if crate::event_processor::process_unicode_escape_events(
1,700✔
166
                    &taken,
1,700✔
167
                    &mut self.content_builder,
1,700✔
168
                )? =>
336✔
169
                {
336✔
170
                    // Unicode escape events handled by shared function
336✔
171
                }
336✔
172
                ujson::Event::End(
173
                    escape_token @ (crate::ujson::EventToken::EscapeQuote
674✔
174
                    | crate::ujson::EventToken::EscapeBackslash
175
                    | crate::ujson::EventToken::EscapeSlash
176
                    | crate::ujson::EventToken::EscapeBackspace
177
                    | crate::ujson::EventToken::EscapeFormFeed
178
                    | crate::ujson::EventToken::EscapeNewline
179
                    | crate::ujson::EventToken::EscapeCarriageReturn
180
                    | crate::ujson::EventToken::EscapeTab),
181
                ) => {
182
                    // StreamParser-specific: Handle simple escape sequences on End events
183
                    // because StreamBuffer must wait until the token ends to accumulate
184
                    // all bytes before processing the complete escape sequence
185
                    crate::event_processor::process_simple_escape_event(
674✔
186
                        &escape_token,
674✔
187
                        &mut self.content_builder,
674✔
NEW
188
                    )?;
×
189
                }
190
                _ => {
674✔
191
                    // All other events continue to next iteration
674✔
192
                }
674✔
193
            }
194
        }
195
    }
4,968✔
196

197
    /// Extract number with proper StreamParser document end detection
198
    fn extract_number_with_finished_state(
253✔
199
        &mut self,
253✔
200
        from_container_end: bool,
253✔
201
    ) -> Result<Event<'_, '_>, ParseError> {
253✔
202
        let start_pos = match *self.content_builder.parser_state() {
253✔
203
            crate::shared::State::Number(pos) => pos,
253✔
NEW
204
            _ => return Err(crate::shared::UnexpectedState::StateMismatch.into()),
×
205
        };
206

207
        *self.content_builder.parser_state_mut() = crate::shared::State::None;
253✔
208

209
        // Use the new ContentBuilder::extract_number method with finished state
210
        use crate::content_builder::ContentBuilder;
211
        self.content_builder
253✔
212
            .extract_number(start_pos, from_container_end, self.finished)
253✔
213
    }
253✔
214

215
    /// Fill buffer from reader
216
    fn fill_buffer_from_reader(&mut self) -> Result<(), ParseError> {
6,908✔
217
        if let Some(fill_slice) = self.content_builder.stream_buffer_mut().get_fill_slice() {
6,908✔
218
            let bytes_read = self
5,118✔
219
                .reader
5,118✔
220
                .read(fill_slice)
5,118✔
221
                .map_err(|_| ParseError::ReaderError)?;
5,118✔
222

223
            self.content_builder
5,118✔
224
                .stream_buffer_mut()
5,118✔
225
                .mark_filled(bytes_read)?;
5,118✔
226
        } else {
227
            // Buffer is full - ALWAYS attempt compaction
228
            let compact_start_pos = match *self.content_builder.parser_state_mut() {
1,790✔
229
                crate::shared::State::Number(start_pos) => start_pos,
401✔
230
                crate::shared::State::Key(start_pos) => start_pos,
126✔
231
                crate::shared::State::String(start_pos) => start_pos,
702✔
232
                _ => self.content_builder.stream_buffer().current_position(),
561✔
233
            };
234

235
            let offset = self
1,790✔
236
                .content_builder
1,790✔
237
                .stream_buffer_mut()
1,790✔
238
                .compact_from(compact_start_pos)?;
1,790✔
239

240
            if offset == 0 {
1,790✔
241
                // SOL: Buffer too small for current token
242
                return Err(ParseError::ScratchBufferFull);
529✔
243
            }
1,261✔
244

245
            // Update parser state positions
246
            self.update_positions_after_compaction(offset)?;
1,261✔
247

248
            // Try to fill again after compaction
249
            if let Some(fill_slice) = self.content_builder.stream_buffer_mut().get_fill_slice() {
1,261✔
250
                let bytes_read = self
1,261✔
251
                    .reader
1,261✔
252
                    .read(fill_slice)
1,261✔
253
                    .map_err(|_| ParseError::ReaderError)?;
1,261✔
254

255
                self.content_builder
1,261✔
256
                    .stream_buffer_mut()
1,261✔
257
                    .mark_filled(bytes_read)?;
1,261✔
UNCOV
258
            }
×
259
        }
260
        Ok(())
6,379✔
261
    }
6,908✔
262

263
    /// Update parser state positions after buffer compaction
264
    fn update_positions_after_compaction(&mut self, offset: usize) -> Result<(), ParseError> {
1,261✔
265
        // Check for positions that would be discarded and need escape mode
266
        // CRITICAL: Position 0 is never discarded, regardless of offset
267
        let needs_escape_mode = match self.content_builder.parser_state_mut() {
1,261✔
268
            crate::shared::State::Key(pos) if *pos > 0 && *pos < offset => Some((*pos, true)), // true = is_key
96✔
269
            crate::shared::State::String(pos) if *pos > 0 && *pos < offset => Some((*pos, false)), // false = is_string
395✔
270
            crate::shared::State::Number(pos) if *pos > 0 && *pos < offset => {
209✔
271
                return Err(ParseError::ScratchBufferFull);
×
272
            }
273
            _ => None,
1,261✔
274
        };
275

276
        // Handle escape mode transition if needed
277
        if let Some((original_pos, is_key)) = needs_escape_mode {
1,261✔
278
            if is_key {
×
279
                self.switch_key_to_escape_mode(original_pos, offset)?;
×
280
            } else {
281
                self.switch_string_to_escape_mode(original_pos, offset)?;
×
282
            }
283
        }
1,261✔
284

285
        // Update positions
286
        match self.content_builder.parser_state_mut() {
1,261✔
287
            crate::shared::State::None => {
561✔
288
                // No position-based state to update
561✔
289
            }
561✔
290
            crate::shared::State::Key(pos) => {
96✔
291
                if *pos > 0 && *pos < offset {
96✔
292
                    *pos = 0; // Reset for escape mode
×
293
                } else if *pos >= offset {
96✔
294
                    *pos = pos.checked_sub(offset).unwrap_or(0); // Safe position adjustment
96✔
295
                }
96✔
296
                // else: *pos == 0 or *pos < offset with pos == 0, keep as-is
297
            }
298
            crate::shared::State::String(pos) => {
395✔
299
                if *pos > 0 && *pos < offset {
395✔
300
                    *pos = 0; // Reset for escape mode
×
301
                } else if *pos >= offset {
395✔
302
                    *pos = pos.checked_sub(offset).unwrap_or(0); // Safe position adjustment
395✔
303
                }
395✔
304
                // else: *pos == 0 or *pos < offset with pos == 0, keep as-is
305
            }
306
            crate::shared::State::Number(pos) => {
209✔
307
                if *pos >= offset {
209✔
308
                    *pos = pos.checked_sub(offset).unwrap_or(0); // Safe position adjustment
209✔
309
                } else {
209✔
310
                    *pos = 0; // Reset for discarded number start
×
311
                }
×
312
            }
313
        }
314

315
        Ok(())
1,261✔
316
    }
1,261✔
317

318
    /// Switch key processing to escape/copy mode when original position was discarded
319
    fn switch_key_to_escape_mode(
×
320
        &mut self,
×
321
        original_pos: usize,
×
322
        offset: usize,
×
323
    ) -> Result<(), ParseError> {
×
324
        // The key start position was in the discarded portion of the buffer
325

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

329
        // Calculate how much actual key content was discarded
330
        let content_start = original_pos; // Key content starts at original_pos (now tracks content directly)
×
331
        let discarded_content = offset.saturating_sub(content_start);
×
332

333
        if discarded_content > 0 {
×
334
            // We lost some actual key content - this would require content recovery
335
            // For now, this is unsupported
336
            return Err(ParseError::ScratchBufferFull);
×
337
        }
×
338

339
        // No actual content was discarded, we can continue parsing
340
        // We can continue parsing the key from the current position
341
        Ok(())
×
342
    }
×
343

344
    /// Switch string processing to escape/copy mode when original position was discarded
345
    fn switch_string_to_escape_mode(
×
346
        &mut self,
×
347
        original_pos: usize,
×
348
        offset: usize,
×
349
    ) -> Result<(), ParseError> {
×
350
        // The string start position was in the discarded portion of the buffer
351

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

355
        // Calculate how much actual string content was discarded
356
        let content_start = original_pos; // String content starts at original_pos (now tracks content directly)
×
357
        let discarded_content = offset.saturating_sub(content_start);
×
358

359
        if discarded_content > 0 {
×
360
            // We lost some actual string content - this would require content recovery
361
            // For now, this is unsupported
362
            return Err(ParseError::ScratchBufferFull);
×
363
        }
×
364

365
        // No actual content was discarded, we can continue parsing
366
        // We can continue parsing the string from the current position
367
        Ok(())
×
368
    }
×
369

370
    /// Handle byte accumulation for strings/keys and Unicode escape sequences
371
    fn handle_byte_accumulation(&mut self, byte: u8) -> Result<(), ParseError> {
11,249✔
372
        // Use ContentBuilder's literal byte append logic
373
        use crate::content_builder::ContentBuilder;
374
        ContentBuilder::append_literal_byte(&mut self.content_builder, byte)
11,249✔
375
    }
11,249✔
376
}
377

378
impl<'b, R: Reader, C: BitStackConfig> PullParser for StreamParser<'b, R, C> {
379
    fn next_event(&mut self) -> Result<Event<'_, '_>, ParseError> {
4,968✔
380
        self.content_builder.apply_unescaped_reset_if_queued();
4,968✔
381

382
        self.next_event_impl()
4,968✔
383
    }
4,968✔
384
}
385

386
impl<'b, R: Reader, C: BitStackConfig> crate::shared::ByteProvider for StreamParser<'b, R, C> {
387
    fn next_byte(&mut self) -> Result<Option<u8>, ParseError> {
19,365✔
388
        // If buffer is empty, try to fill it first
389
        if self.content_builder.stream_buffer().is_empty() {
19,365✔
390
            self.fill_buffer_from_reader()?;
6,908✔
391
        }
12,457✔
392

393
        // If still empty after fill attempt, we're at EOF
394
        if self.content_builder.stream_buffer().is_empty() {
18,836✔
395
            return Ok(None);
500✔
396
        }
18,336✔
397

398
        // Get byte and advance
399
        let byte = self.content_builder.stream_buffer().current_byte()?;
18,336✔
400
        self.content_builder.stream_buffer_mut().advance()?;
18,336✔
401
        Ok(Some(byte))
18,336✔
402
    }
19,365✔
403
}
404

405
#[cfg(test)]
406
mod tests {
407
    use super::*;
408

409
    /// Simple test reader that reads from a byte slice
410
    pub struct SliceReader<'a> {
411
        data: &'a [u8],
412
        position: usize,
413
    }
414

415
    impl<'a> SliceReader<'a> {
416
        pub fn new(data: &'a [u8]) -> Self {
39✔
417
            Self { data, position: 0 }
39✔
418
        }
39✔
419
    }
420

421
    impl Reader for SliceReader<'_> {
422
        type Error = ();
423

424
        fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
69✔
425
            let remaining = self.data.len().saturating_sub(self.position);
69✔
426
            if remaining == 0 {
69✔
427
                return Ok(0); // EOF
30✔
428
            }
39✔
429

430
            let to_copy = remaining.min(buf.len());
39✔
431
            let end_pos = self.position.saturating_add(to_copy);
39✔
432
            if let (Some(dest), Some(src)) = (
39✔
433
                buf.get_mut(..to_copy),
39✔
434
                self.data.get(self.position..end_pos),
39✔
435
            ) {
436
                dest.copy_from_slice(src);
39✔
437
                self.position = end_pos;
39✔
438
                Ok(to_copy)
39✔
439
            } else {
440
                Err(())
×
441
            }
442
        }
69✔
443
    }
444

445
    type TestStreamParser<'b> = StreamParser<'b, SliceReader<'static>>;
446

447
    #[test]
448
    fn test_direct_parser_simple_object() {
1✔
449
        let json = b"{}";
1✔
450
        let reader = SliceReader::new(json);
1✔
451
        let mut buffer = [0u8; 256];
1✔
452
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
453

454
        // Should get ObjectStart
455
        let event = parser.next_event().unwrap();
1✔
456
        assert!(matches!(event, Event::StartObject));
1✔
457

458
        // Should get ObjectEnd
459
        let event = parser.next_event().unwrap();
1✔
460
        assert!(matches!(event, Event::EndObject));
1✔
461

462
        // Should get EndDocument
463
        let event = parser.next_event().unwrap();
1✔
464
        assert!(matches!(event, Event::EndDocument));
1✔
465
    }
1✔
466

467
    #[test]
468
    fn test_direct_parser_simple_array() {
1✔
469
        let json = b"[]";
1✔
470
        let reader = SliceReader::new(json);
1✔
471
        let mut buffer = [0u8; 256];
1✔
472
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
473

474
        // Should get ArrayStart
475
        let event = parser.next_event().unwrap();
1✔
476
        assert!(matches!(event, Event::StartArray));
1✔
477

478
        // Should get ArrayEnd
479
        let event = parser.next_event().unwrap();
1✔
480
        assert!(matches!(event, Event::EndArray));
1✔
481

482
        // Should get EndDocument
483
        let event = parser.next_event().unwrap();
1✔
484
        assert!(matches!(event, Event::EndDocument));
1✔
485
    }
1✔
486

487
    #[test_log::test]
488
    fn test_direct_parser_simple_escape() {
489
        let json = b"\"hello\\nworld\"";
490
        let reader = SliceReader::new(json);
491
        let mut buffer = [0u8; 256];
492
        let mut parser = TestStreamParser::new(reader, &mut buffer);
493

494
        if let Event::String(json_string) = parser.next_event().unwrap() {
495
            assert_eq!(json_string.as_str(), "hello\nworld");
496
        } else {
497
            panic!("Expected String event");
498
        }
499
    }
500

501
    #[test]
502
    fn test_pending_state_edge_cases() {
1✔
503
        // Test 1: Complex nested container endings
504
        let json1 = br#"{"a": {"b": [{"c": 123}]}}"#;
1✔
505
        let reader1 = SliceReader::new(json1);
1✔
506
        let mut buffer1 = [0u8; 256];
1✔
507
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
508

509
        let mut events = Vec::new();
1✔
510
        loop {
511
            match parser1.next_event() {
13✔
512
                Ok(Event::EndDocument) => break,
1✔
513
                Ok(event) => events.push(format!("{:?}", event)),
12✔
514
                Err(e) => panic!("Nested containers failed: {:?}", e),
×
515
            }
516
        }
517

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

521
        // Test 2: Mixed types after numbers in array
522
        let json2 = br#"[123, "string", true, null, 456]"#;
1✔
523
        let reader2 = SliceReader::new(json2);
1✔
524
        let mut buffer2 = [0u8; 256];
1✔
525
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
526

527
        let mut number_count = 0;
1✔
528
        loop {
529
            match parser2.next_event() {
8✔
530
                Ok(Event::EndDocument) => break,
1✔
531
                Ok(Event::Number(_)) => number_count += 1,
2✔
532
                Ok(_) => {}
5✔
533
                Err(e) => panic!("Mixed types failed: {:?}", e),
×
534
            }
535
        }
536
        assert_eq!(number_count, 2); // Should find both 123 and 456
1✔
537

538
        // Test 3: Empty containers
539
        let json3 = br#"[[], {}, [{}], {"empty": []}]"#;
1✔
540
        let reader3 = SliceReader::new(json3);
1✔
541
        let mut buffer3 = [0u8; 256];
1✔
542
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
543

544
        loop {
545
            match parser3.next_event() {
16✔
546
                Ok(Event::EndDocument) => break,
1✔
547
                Ok(_) => {}
15✔
548
                Err(e) => panic!("Empty containers failed: {:?}", e),
×
549
            }
550
        }
551

552
        // Test 4: Multiple consecutive numbers
553
        let json4 = br#"[1, 2, 3, 4, 5]"#;
1✔
554
        let reader4 = SliceReader::new(json4);
1✔
555
        let mut buffer4 = [0u8; 256];
1✔
556
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
1✔
557

558
        let mut consecutive_numbers = Vec::new();
1✔
559
        loop {
560
            match parser4.next_event() {
8✔
561
                Ok(Event::EndDocument) => break,
1✔
562
                Ok(Event::Number(n)) => consecutive_numbers.push(n.as_str().to_string()),
5✔
563
                Ok(_) => {}
2✔
564
                Err(e) => panic!("Consecutive numbers failed: {:?}", e),
×
565
            }
566
        }
567
        assert_eq!(consecutive_numbers, vec!["1", "2", "3", "4", "5"]);
1✔
568
    }
1✔
569

570
    #[test]
571
    fn test_error_recovery_with_pending_state() {
1✔
572
        // Test error handling - this should fail gracefully without hanging onto pending state
573
        let invalid_json = br#"{"key": 123,"#; // Missing closing brace
1✔
574
        let reader = SliceReader::new(invalid_json);
1✔
575
        let mut buffer = [0u8; 256];
1✔
576
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
577

578
        // Parse until we hit an error or EOF
579
        loop {
580
            match parser.next_event() {
4✔
581
                Ok(Event::EndDocument) => break, // EOF reached
×
582
                Ok(_) => {}
3✔
583
                Err(_) => break, // Error occurred - this is expected
1✔
584
            }
585
        }
586

587
        // The important thing is that we don't panic or hang
588
        // The specific error behavior may vary
589
    }
1✔
590

591
    #[test]
592
    fn test_multiple_rapid_container_ends() {
1✔
593
        // Test deeply nested structures that end with numbers
594
        // This tests whether we can handle multiple rapid container ends correctly
595

596
        // Test 1: Deeply nested arrays ending with number
597
        let json1 = br#"[[[123]]]"#;
1✔
598
        let reader1 = SliceReader::new(json1);
1✔
599
        let mut buffer1 = [0u8; 256];
1✔
600
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
601

602
        let mut events1 = Vec::new();
1✔
603
        loop {
604
            match parser1.next_event() {
8✔
605
                Ok(Event::EndDocument) => break,
1✔
606
                Ok(event) => events1.push(format!("{:?}", event)),
7✔
607
                Err(e) => panic!("Deeply nested arrays failed: {:?}", e),
×
608
            }
609
        }
610

611
        // Should have: StartArray, StartArray, StartArray, Number(123), EndArray, EndArray, EndArray
612
        assert_eq!(events1.len(), 7);
1✔
613
        assert!(events1[3].contains("Number"));
1✔
614
        assert_eq!(&events1[4], "EndArray");
1✔
615
        assert_eq!(&events1[5], "EndArray");
1✔
616
        assert_eq!(&events1[6], "EndArray");
1✔
617

618
        // Test 2: Mixed nested containers ending with number
619
        let json2 = br#"{"a": [{"b": 456}]}"#;
1✔
620
        let reader2 = SliceReader::new(json2);
1✔
621
        let mut buffer2 = [0u8; 256];
1✔
622
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
623

624
        let mut events2 = Vec::new();
1✔
625
        loop {
626
            match parser2.next_event() {
10✔
627
                Ok(Event::EndDocument) => break,
1✔
628
                Ok(event) => events2.push(format!("{:?}", event)),
9✔
629
                Err(e) => panic!("Mixed nested containers failed: {:?}", e),
×
630
            }
631
        }
632

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

636
        // Test 3: Multiple numbers at different nesting levels
637
        let json3 = br#"[123, [456, [789]]]"#;
1✔
638
        let reader3 = SliceReader::new(json3);
1✔
639
        let mut buffer3 = [0u8; 256];
1✔
640
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
641

642
        let mut number_count = 0;
1✔
643
        let mut events3 = Vec::new();
1✔
644
        loop {
645
            match parser3.next_event() {
10✔
646
                Ok(Event::EndDocument) => break,
1✔
647
                Ok(Event::Number(n)) => {
3✔
648
                    number_count += 1;
3✔
649
                    events3.push(format!("Number({})", n.as_str()));
3✔
650
                }
3✔
651
                Ok(event) => events3.push(format!("{:?}", event)),
6✔
652
                Err(e) => panic!("Multiple nested numbers failed: {:?}", e),
×
653
            }
654
        }
655

656
        assert_eq!(number_count, 3); // Should find all three numbers: 123, 456, 789
1✔
657
    }
1✔
658

659
    #[test]
660
    fn test_pending_flag_priority() {
1✔
661
        // Defensive test: ensure that if both pending flags were somehow set,
662
        // we handle it gracefully (this shouldn't happen in normal operation)
663

664
        let json = br#"[{"key": 123}]"#;
1✔
665
        let reader = SliceReader::new(json);
1✔
666
        let mut buffer = [0u8; 256];
1✔
667
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
668

669
        // Parse normally - this should work fine and never set both flags
670
        let mut events = Vec::new();
1✔
671
        loop {
672
            match parser.next_event() {
7✔
673
                Ok(Event::EndDocument) => break,
1✔
674
                Ok(event) => events.push(format!("{:?}", event)),
6✔
675
                Err(e) => panic!("Flag priority test failed: {:?}", e),
×
676
            }
677
        }
678

679
        // Should successfully parse: StartArray, StartObject, Key, Number, EndObject, EndArray
680
        assert_eq!(events.len(), 6);
1✔
681
        assert!(events[3].contains("Number"));
1✔
682
        assert_eq!(&events[4], "EndObject");
1✔
683
        assert_eq!(&events[5], "EndArray");
1✔
684
    }
1✔
685

686
    #[test]
687
    fn test_direct_parser_array_of_strings() {
1✔
688
        let json = b"[\"first\", \"second\"]";
1✔
689
        let reader = SliceReader::new(json);
1✔
690
        let mut buffer = [0u8; 256];
1✔
691
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
692

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

695
        if let Event::String(s1) = parser.next_event().unwrap() {
1✔
696
            assert_eq!(s1.as_str(), "first");
1✔
697
        } else {
698
            panic!("Expected String event");
×
699
        }
700

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

707
        assert!(matches!(parser.next_event().unwrap(), Event::EndArray));
1✔
708
    }
1✔
709

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

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

719
        // First key-value pair
720
        if let Event::Key(key1) = parser.next_event().unwrap() {
1✔
721
            assert_eq!(key1.as_str(), "name");
1✔
722
        } else {
723
            panic!("Expected Key event");
×
724
        }
725

726
        if let Event::String(val1) = parser.next_event().unwrap() {
1✔
727
            assert_eq!(val1.as_str(), "value");
1✔
728
        } else {
729
            panic!("Expected String event");
×
730
        }
731

732
        // Second key-value pair
733
        if let Event::Key(key2) = parser.next_event().unwrap() {
1✔
734
            assert_eq!(key2.as_str(), "count");
1✔
735
        } else {
736
            panic!("Expected Key event");
×
737
        }
738

739
        if let Event::String(val2) = parser.next_event().unwrap() {
1✔
740
            assert_eq!(val2.as_str(), "42");
1✔
741
        } else {
742
            panic!("Expected String event");
×
743
        }
744

745
        assert!(matches!(parser.next_event().unwrap(), Event::EndObject));
1✔
746
    }
1✔
747

748
    #[test]
749
    fn test_direct_parser_multiple_escapes() {
1✔
750
        let json = b"\"line1\\nline2\\ttab\\\"quote\"";
1✔
751
        let reader = SliceReader::new(json);
1✔
752
        let mut buffer = [0u8; 256];
1✔
753
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
754

755
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
756
            let content = json_string.as_str();
1✔
757
            // Check that escape sequences were properly processed
758
            let has_newline = content.contains('\n');
1✔
759
            let has_tab = content.contains('\t');
1✔
760
            let has_quote = content.contains('"');
1✔
761

762
            // These should be real control characters, not literal \n \t \"
763
            assert!(has_newline, "Should contain actual newline character");
1✔
764
            assert!(has_tab, "Should contain actual tab character");
1✔
765
            assert!(has_quote, "Should contain actual quote character");
1✔
766
        } else {
767
            panic!("Expected String event");
×
768
        }
769
    }
1✔
770

771
    #[test]
772
    fn test_direct_parser_unicode_escape() {
1✔
773
        let json = b"\"Hello \\u0041\\u03B1\""; // Hello A(alpha)
1✔
774
        let reader = SliceReader::new(json);
1✔
775
        let mut buffer = [0u8; 256];
1✔
776
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
777

778
        if let Event::String(json_string) = parser.next_event().unwrap() {
1✔
779
            let content = json_string.as_str();
1✔
780
            // Should be "Hello A⍺" (with actual A and alpha characters)
781
            assert!(content.contains('A'));
1✔
782
            // Note: This test will initially fail until we implement Unicode escapes
783
        } else {
784
            panic!("Expected String event");
×
785
        }
786
    }
1✔
787

788
    #[test]
789
    fn test_direct_parser_boolean_true() {
1✔
790
        let json = b"true";
1✔
791
        let reader = SliceReader::new(json);
1✔
792
        let mut buffer = [0u8; 256];
1✔
793
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
794

795
        let event = parser.next_event().unwrap();
1✔
796
        assert_eq!(event, Event::Bool(true));
1✔
797

798
        let event = parser.next_event().unwrap();
1✔
799
        assert_eq!(event, Event::EndDocument);
1✔
800
    }
1✔
801

802
    #[test]
803
    fn test_direct_parser_boolean_false() {
1✔
804
        let json = b"false";
1✔
805
        let reader = SliceReader::new(json);
1✔
806
        let mut buffer = [0u8; 256];
1✔
807
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
808

809
        let event = parser.next_event().unwrap();
1✔
810
        assert_eq!(event, Event::Bool(false));
1✔
811

812
        let event = parser.next_event().unwrap();
1✔
813
        assert_eq!(event, Event::EndDocument);
1✔
814
    }
1✔
815

816
    #[test]
817
    fn test_direct_parser_null() {
1✔
818
        let json = b"null";
1✔
819
        let reader = SliceReader::new(json);
1✔
820
        let mut buffer = [0u8; 256];
1✔
821
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
822

823
        let event = parser.next_event().unwrap();
1✔
824
        assert_eq!(event, Event::Null);
1✔
825

826
        let event = parser.next_event().unwrap();
1✔
827
        assert_eq!(event, Event::EndDocument);
1✔
828
    }
1✔
829

830
    #[test]
831
    fn test_direct_parser_booleans_in_array() {
1✔
832
        let json = b"[true, false, null]";
1✔
833
        let reader = SliceReader::new(json);
1✔
834
        let mut buffer = [0u8; 256];
1✔
835
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
836

837
        assert_eq!(parser.next_event().unwrap(), Event::StartArray);
1✔
838
        assert_eq!(parser.next_event().unwrap(), Event::Bool(true));
1✔
839
        assert_eq!(parser.next_event().unwrap(), Event::Bool(false));
1✔
840
        assert_eq!(parser.next_event().unwrap(), Event::Null);
1✔
841
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1✔
842
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
843
    }
1✔
844

845
    #[test]
846
    fn test_direct_parser_number_simple() {
1✔
847
        let json = b"42";
1✔
848
        let reader = SliceReader::new(json);
1✔
849
        let mut buffer = [0u8; 256];
1✔
850
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
851

852
        let event = parser.next_event().unwrap();
1✔
853
        if let Event::Number(json_number) = event {
1✔
854
            assert_eq!(json_number.as_str(), "42");
1✔
855
        } else {
856
            panic!("Expected Number event, got: {:?}", event);
×
857
        }
858

859
        let event = parser.next_event().unwrap();
1✔
860
        assert_eq!(event, Event::EndDocument);
1✔
861
    }
1✔
862

863
    #[test]
864
    fn test_direct_parser_number_negative() {
1✔
865
        let json = b"-123";
1✔
866
        let reader = SliceReader::new(json);
1✔
867
        let mut buffer = [0u8; 256];
1✔
868
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
869

870
        let event = parser.next_event().unwrap();
1✔
871
        if let Event::Number(json_number) = event {
1✔
872
            assert_eq!(json_number.as_str(), "-123");
1✔
873
        } else {
874
            panic!("Expected Number event, got: {:?}", event);
×
875
        }
876

877
        let event = parser.next_event().unwrap();
1✔
878
        assert_eq!(event, Event::EndDocument);
1✔
879
    }
1✔
880

881
    #[test]
882
    fn test_direct_parser_number_float() {
1✔
883
        let json = b"3.14159";
1✔
884
        let reader = SliceReader::new(json);
1✔
885
        let mut buffer = [0u8; 256];
1✔
886
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
887

888
        #[cfg(feature = "float-error")]
889
        {
890
            // float-error configuration should return an error for float values
891
            let result = parser.next_event();
892
            assert!(
893
                result.is_err(),
894
                "Expected error for float with float-error configuration"
895
            );
896
            return;
897
        }
898

899
        #[cfg(not(feature = "float-error"))]
900
        {
901
            let event = parser.next_event().unwrap();
1✔
902
            if let Event::Number(json_number) = event {
1✔
903
                assert_eq!(json_number.as_str(), "3.14159");
1✔
904
            } else {
905
                panic!("Expected Number event, got: {:?}", event);
×
906
            }
907

908
            let event = parser.next_event().unwrap();
1✔
909
            assert_eq!(event, Event::EndDocument);
1✔
910
        }
911
    }
1✔
912

913
    #[test]
914
    fn test_direct_parser_numbers_in_array() {
1✔
915
        #[cfg(feature = "float-error")]
916
        let json = b"[42, -7]"; // No floats for float-error config
917
        #[cfg(not(feature = "float-error"))]
918
        let json = b"[42, -7, 3.14]"; // Include float for other configs
1✔
919

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_eq!(parser.next_event().unwrap(), Event::StartArray);
1✔
925

926
        let event = parser.next_event().unwrap();
1✔
927
        if let Event::Number(json_number) = event {
1✔
928
            assert_eq!(json_number.as_str(), "42");
1✔
929
        } else {
930
            panic!("Expected Number event, got: {:?}", event);
×
931
        }
932

933
        let event = parser.next_event().unwrap();
1✔
934
        if let Event::Number(json_number) = event {
1✔
935
            assert_eq!(json_number.as_str(), "-7");
1✔
936
        } else {
937
            panic!("Expected Number event, got: {:?}", event);
×
938
        }
939

940
        #[cfg(not(feature = "float-error"))]
941
        {
942
            let event = parser.next_event().unwrap();
1✔
943
            if let Event::Number(json_number) = event {
1✔
944
                assert_eq!(json_number.as_str(), "3.14");
1✔
945
            } else {
946
                panic!("Expected Number event, got: {:?}", event);
×
947
            }
948
        }
949

950
        assert_eq!(parser.next_event().unwrap(), Event::EndArray);
1✔
951
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
952
    }
1✔
953

954
    #[test]
955
    fn test_direct_parser_numbers_in_object() {
1✔
956
        #[cfg(feature = "float-error")]
957
        let json = b"{\"count\": 42, \"score\": -7}"; // No floats for float-error config
958
        #[cfg(not(feature = "float-error"))]
959
        let json = b"{\"count\": 42, \"score\": -7.5}"; // Include float for other configs
1✔
960

961
        let reader = SliceReader::new(json);
1✔
962
        let mut buffer = [0u8; 256];
1✔
963
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
964

965
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
966

967
        // First key-value pair
968
        if let Event::Key(key1) = parser.next_event().unwrap() {
1✔
969
            assert_eq!(key1.as_str(), "count");
1✔
970
        } else {
971
            panic!("Expected Key event");
×
972
        }
973

974
        if let Event::Number(val1) = parser.next_event().unwrap() {
1✔
975
            assert_eq!(val1.as_str(), "42");
1✔
976
        } else {
977
            panic!("Expected Number event");
×
978
        }
979

980
        // Second key-value pair
981
        if let Event::Key(key2) = parser.next_event().unwrap() {
1✔
982
            assert_eq!(key2.as_str(), "score");
1✔
983
        } else {
984
            panic!("Expected Key event");
×
985
        }
986

987
        if let Event::Number(val2) = parser.next_event().unwrap() {
1✔
988
            #[cfg(feature = "float-error")]
989
            assert_eq!(val2.as_str(), "-7");
990
            #[cfg(not(feature = "float-error"))]
991
            assert_eq!(val2.as_str(), "-7.5");
1✔
992
        } else {
993
            panic!("Expected Number event");
×
994
        }
995

996
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
997
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
998
    }
1✔
999

1000
    #[test]
1001
    fn test_direct_parser_no_float_configuration() {
1✔
1002
        // Test that StreamParser properly uses unified number parsing with no-float config
1003
        let json = br#"{"integer": 42, "float": 3.14, "scientific": 1e3}"#;
1✔
1004
        let reader = SliceReader::new(json);
1✔
1005
        let mut buffer = [0u8; 256];
1✔
1006
        let mut parser = TestStreamParser::new(reader, &mut buffer);
1✔
1007

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

1011
        // Integer key-value
1012
        assert_eq!(
1✔
1013
            parser.next_event().unwrap(),
1✔
1014
            Event::Key(crate::String::Borrowed("integer"))
1015
        );
1016
        if let Event::Number(num) = parser.next_event().unwrap() {
1✔
1017
            assert_eq!(num.as_str(), "42");
1✔
1018
            match num.parsed() {
1✔
1019
                crate::NumberResult::Integer(i) => assert_eq!(*i, 42),
1✔
1020
                _ => panic!("Expected integer parsing"),
×
1021
            }
1022
        } else {
1023
            panic!("Expected Number event");
×
1024
        }
1025

1026
        // Float key-value - behavior varies by configuration
1027
        assert_eq!(
1✔
1028
            parser.next_event().unwrap(),
1✔
1029
            Event::Key(crate::String::Borrowed("float"))
1030
        );
1031

1032
        #[cfg(feature = "float-error")]
1033
        {
1034
            // float-error should return an error when encountering floats
1035
            let result = parser.next_event();
1036
            assert!(
1037
                result.is_err(),
1038
                "Expected error for float with float-error configuration"
1039
            );
1040
            // Test ends here for float-error - no more processing needed
1041
        }
1042

1043
        #[cfg(not(feature = "float-error"))]
1044
        {
1045
            if let Event::Number(num) = parser.next_event().unwrap() {
1✔
1046
                assert_eq!(num.as_str(), "3.14");
1✔
1047
                // In no-float configuration, this should be FloatDisabled
1048
                match num.parsed() {
1✔
1049
                    #[cfg(not(feature = "float"))]
1050
                    crate::NumberResult::FloatDisabled => {
1051
                        // This is expected in no-float build
1052
                    }
1053
                    #[cfg(feature = "float")]
1054
                    crate::NumberResult::Float(f) => {
1✔
1055
                        // This is expected in float-enabled build
1056
                        assert!((f - 3.14).abs() < 0.01);
1✔
1057
                    }
1058
                    #[cfg(feature = "float-skip")]
1059
                    crate::NumberResult::FloatSkipped => {
1060
                        // This is expected in float-skip build
1061
                    }
1062
                    #[cfg(feature = "float-truncate")]
1063
                    crate::NumberResult::FloatTruncated(i) => {
1064
                        // This is expected in float-truncate build (3.14 -> 3)
1065
                        assert_eq!(*i, 3);
1066
                    }
1067
                    _ => panic!("Unexpected number parsing result for float"),
×
1068
                }
1069
            } else {
1070
                panic!("Expected Number event");
×
1071
            }
1072

1073
            // Scientific notation handling varies by float configuration
1074
            assert_eq!(
1✔
1075
                parser.next_event().unwrap(),
1✔
1076
                Event::Key(crate::String::Borrowed("scientific"))
1077
            );
1078

1079
            // float-truncate rejects scientific notation, so test should end early for that config
1080
            #[cfg(feature = "float-truncate")]
1081
            {
1082
                // float-truncate rejects scientific notation since it would require float math
1083
                let result = parser.next_event();
1084
                assert!(
1085
                    result.is_err(),
1086
                    "Expected error for scientific notation with float-truncate"
1087
                );
1088
                // Test ends here for float-truncate - no more processing needed
1089
            }
1090

1091
            #[cfg(not(feature = "float-truncate"))]
1092
            {
1093
                if let Event::Number(num) = parser.next_event().unwrap() {
1✔
1094
                    assert_eq!(num.as_str(), "1e3");
1✔
1095
                    match num.parsed() {
1✔
1096
                        #[cfg(not(feature = "float"))]
1097
                        crate::NumberResult::FloatDisabled => {
1098
                            // This is expected in no-float build - raw string preserved for manual parsing
1099
                        }
1100
                        #[cfg(feature = "float-skip")]
1101
                        crate::NumberResult::FloatSkipped => {
1102
                            // This is expected in float-skip build
1103
                        }
1104
                        #[cfg(feature = "float")]
1105
                        crate::NumberResult::Float(f) => {
1✔
1106
                            // This is expected in float-enabled build
1107
                            assert!((f - 1000.0).abs() < f64::EPSILON);
1✔
1108
                        }
1109
                        _ => panic!("Unexpected number parsing result for scientific notation"),
×
1110
                    }
1111
                } else {
1112
                    panic!("Expected Number event");
×
1113
                }
1114

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

1121
    #[test]
1122
    fn test_number_parsing_delimiter_exclusion() {
1✔
1123
        // Test that numbers don't include trailing delimiters in various contexts
1124

1125
        // Test 1: Number followed by array end
1126
        let json1 = b"[123]";
1✔
1127
        let reader1 = SliceReader::new(json1);
1✔
1128
        let mut buffer1 = [0u8; 256];
1✔
1129
        let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
1✔
1130

1131
        assert!(matches!(parser1.next_event().unwrap(), Event::StartArray));
1✔
1132
        if let Event::Number(num) = parser1.next_event().unwrap() {
1✔
1133
            assert_eq!(
1✔
1134
                num.as_str(),
1✔
1135
                "123",
1136
                "Number should not include trailing delimiter ']'"
×
1137
            );
1138
        } else {
1139
            panic!("Expected Number event");
×
1140
        }
1141
        assert!(matches!(parser1.next_event().unwrap(), Event::EndArray));
1✔
1142

1143
        // Test 2: Number followed by object end
1144
        let json2 = b"{\"key\":456}";
1✔
1145
        let reader2 = SliceReader::new(json2);
1✔
1146
        let mut buffer2 = [0u8; 256];
1✔
1147
        let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
1✔
1148

1149
        assert!(matches!(parser2.next_event().unwrap(), Event::StartObject));
1✔
1150
        assert!(matches!(parser2.next_event().unwrap(), Event::Key(_)));
1✔
1151
        if let Event::Number(num) = parser2.next_event().unwrap() {
1✔
1152
            assert_eq!(
1✔
1153
                num.as_str(),
1✔
1154
                "456",
1155
                "Number should not include trailing delimiter '}}'"
×
1156
            );
1157
        } else {
1158
            panic!("Expected Number event");
×
1159
        }
1160
        assert!(matches!(parser2.next_event().unwrap(), Event::EndObject));
1✔
1161

1162
        // Test 3: Number followed by comma in array
1163
        let json3 = b"[789,10]";
1✔
1164
        let reader3 = SliceReader::new(json3);
1✔
1165
        let mut buffer3 = [0u8; 256];
1✔
1166
        let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
1✔
1167

1168
        assert!(matches!(parser3.next_event().unwrap(), Event::StartArray));
1✔
1169
        if let Event::Number(num1) = parser3.next_event().unwrap() {
1✔
1170
            assert_eq!(
1✔
1171
                num1.as_str(),
1✔
1172
                "789",
1173
                "First number should not include trailing delimiter ','"
×
1174
            );
1175
        } else {
1176
            panic!("Expected first Number event");
×
1177
        }
1178
        if let Event::Number(num2) = parser3.next_event().unwrap() {
1✔
1179
            assert_eq!(
1✔
1180
                num2.as_str(),
1✔
1181
                "10",
1182
                "Second number should not include trailing delimiter ']'"
×
1183
            );
1184
        } else {
1185
            panic!("Expected second Number event");
×
1186
        }
1187
        assert!(matches!(parser3.next_event().unwrap(), Event::EndArray));
1✔
1188

1189
        // Test 4: Number followed by comma in object
1190
        let json4 = b"{\"a\":11,\"b\":22}";
1✔
1191
        let reader4 = SliceReader::new(json4);
1✔
1192
        let mut buffer4 = [0u8; 256];
1✔
1193
        let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
1✔
1194

1195
        assert!(matches!(parser4.next_event().unwrap(), Event::StartObject));
1✔
1196
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1✔
1197
        if let Event::Number(num1) = parser4.next_event().unwrap() {
1✔
1198
            assert_eq!(
1✔
1199
                num1.as_str(),
1✔
1200
                "11",
1201
                "First number should not include trailing delimiter ','"
×
1202
            );
1203
        } else {
1204
            panic!("Expected first Number event");
×
1205
        }
1206
        assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
1✔
1207
        if let Event::Number(num2) = parser4.next_event().unwrap() {
1✔
1208
            assert_eq!(
1✔
1209
                num2.as_str(),
1✔
1210
                "22",
1211
                "Second number should not include trailing delimiter '}}'"
×
1212
            );
1213
        } else {
1214
            panic!("Expected second Number event");
×
1215
        }
1216
        assert!(matches!(parser4.next_event().unwrap(), Event::EndObject));
1✔
1217

1218
        // Test 5: Standalone number at end of document (should include full content)
1219
        let json5 = b"999";
1✔
1220
        let reader5 = SliceReader::new(json5);
1✔
1221
        let mut buffer5 = [0u8; 256];
1✔
1222
        let mut parser5 = TestStreamParser::new(reader5, &mut buffer5);
1✔
1223

1224
        if let Event::Number(num) = parser5.next_event().unwrap() {
1✔
1225
            assert_eq!(
1✔
1226
                num.as_str(),
1✔
1227
                "999",
1228
                "Standalone number should include full content"
×
1229
            );
1230
        } else {
1231
            panic!("Expected Number event");
×
1232
        }
1233
        assert!(matches!(parser5.next_event().unwrap(), Event::EndDocument));
1✔
1234

1235
        // Test 6: Negative numbers with delimiters
1236
        let json6 = b"[-42,33]";
1✔
1237
        let reader6 = SliceReader::new(json6);
1✔
1238
        let mut buffer6 = [0u8; 256];
1✔
1239
        let mut parser6 = TestStreamParser::new(reader6, &mut buffer6);
1✔
1240

1241
        assert!(matches!(parser6.next_event().unwrap(), Event::StartArray));
1✔
1242
        if let Event::Number(num1) = parser6.next_event().unwrap() {
1✔
1243
            assert_eq!(
1✔
1244
                num1.as_str(),
1✔
1245
                "-42",
1246
                "Negative number should not include trailing delimiter ','"
×
1247
            );
1248
        } else {
1249
            panic!("Expected first Number event");
×
1250
        }
1251
        if let Event::Number(num2) = parser6.next_event().unwrap() {
1✔
1252
            assert_eq!(
1✔
1253
                num2.as_str(),
1✔
1254
                "33",
1255
                "Second number should not include trailing delimiter ']'"
×
1256
            );
1257
        } else {
1258
            panic!("Expected second Number event");
×
1259
        }
1260
        assert!(matches!(parser6.next_event().unwrap(), Event::EndArray));
1✔
1261

1262
        // Test 7: Decimal numbers with delimiters (if float enabled)
1263
        #[cfg(not(feature = "float-error"))]
1264
        {
1265
            let json7 = b"[3.14,2.71]";
1✔
1266
            let reader7 = SliceReader::new(json7);
1✔
1267
            let mut buffer7 = [0u8; 256];
1✔
1268
            let mut parser7 = TestStreamParser::new(reader7, &mut buffer7);
1✔
1269

1270
            assert!(matches!(parser7.next_event().unwrap(), Event::StartArray));
1✔
1271
            if let Event::Number(num1) = parser7.next_event().unwrap() {
1✔
1272
                assert_eq!(
1✔
1273
                    num1.as_str(),
1✔
1274
                    "3.14",
1275
                    "Decimal number should not include trailing delimiter ','"
×
1276
                );
1277
            } else {
1278
                panic!("Expected first Number event");
×
1279
            }
1280
            if let Event::Number(num2) = parser7.next_event().unwrap() {
1✔
1281
                assert_eq!(
1✔
1282
                    num2.as_str(),
1✔
1283
                    "2.71",
1284
                    "Second decimal number should not include trailing delimiter ']'"
×
1285
                );
1286
            } else {
1287
                panic!("Expected second Number event");
×
1288
            }
1289
            assert!(matches!(parser7.next_event().unwrap(), Event::EndArray));
1✔
1290
        }
1291
    }
1✔
1292

1293
    #[test]
1294
    fn test_escape_buffer_functions() {
1✔
1295
        // Test the uncovered escape processing functions
1296
        let json_stream = br#"{"escaped": "test\nstring"}"#;
1✔
1297
        let mut buffer = [0u8; 1024];
1✔
1298
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1✔
1299

1300
        // These functions are private but we can test them through the public API
1301
        // The escape processing should trigger the uncovered functions
1302
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1303
        assert_eq!(
1✔
1304
            parser.next_event().unwrap(),
1✔
1305
            Event::Key(crate::String::Borrowed("escaped"))
1306
        );
1307

1308
        // This should trigger append_byte_to_escape_buffer and queue_unescaped_reset
1309
        if let Event::String(s) = parser.next_event().unwrap() {
1✔
1310
            assert_eq!(s.as_ref(), "test\nstring"); // Escape sequence should be processed
1✔
1311
        } else {
1312
            panic!("Expected String event with escape sequence");
×
1313
        }
1314

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

1319
    #[test]
1320
    fn test_slice_reader_constructor() {
1✔
1321
        // Test the uncovered SliceReader::new function
1322
        let data = b"test data";
1✔
1323
        let reader = SliceReader::new(data);
1✔
1324
        assert_eq!(reader.data, data);
1✔
1325
        assert_eq!(reader.position, 0);
1✔
1326
    }
1✔
1327

1328
    #[test]
1329
    fn test_complex_escape_sequences() {
1✔
1330
        // Test more complex escape processing to cover the escape buffer functions
1331
        let json_stream = br#"{"multi": "line1\nline2\ttab\r\n"}"#;
1✔
1332
        let mut buffer = [0u8; 1024];
1✔
1333
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
1✔
1334

1335
        assert_eq!(parser.next_event().unwrap(), Event::StartObject);
1✔
1336
        assert_eq!(
1✔
1337
            parser.next_event().unwrap(),
1✔
1338
            Event::Key(crate::String::Borrowed("multi"))
1339
        );
1340

1341
        // This should exercise the escape buffer processing extensively
1342
        if let Event::String(s) = parser.next_event().unwrap() {
1✔
1343
            assert_eq!(s.as_ref(), "line1\nline2\ttab\r\n");
1✔
1344
        } else {
1345
            panic!("Expected String event");
×
1346
        }
1347

1348
        assert_eq!(parser.next_event().unwrap(), Event::EndObject);
1✔
1349
        assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
1✔
1350
    }
1✔
1351

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

1358
        println!("Testing escape sequence with buffer size: {}", buffer_size);
3✔
1359
        println!(
3✔
1360
            "JSON input: {:?}",
3✔
1361
            core::str::from_utf8(json_stream).unwrap()
3✔
1362
        );
1363
        let mut buffer = vec![0u8; buffer_size];
3✔
1364
        let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
3✔
1365

1366
        // Array start
1367
        match parser.next_event()? {
3✔
1368
            Event::StartArray => println!("  ✅ StartArray OK"),
3✔
1369
            other => panic!("Expected StartArray, got: {:?}", other),
×
1370
        }
1371

1372
        // String with escape
1373
        match parser.next_event()? {
3✔
1374
            Event::String(s) => {
2✔
1375
                println!("  ✅ String OK: '{}'", s.as_str());
2✔
1376
                assert_eq!(s.as_str(), "hello\\");
2✔
1377
            }
1378
            other => panic!("Expected String, got: {:?}", other),
×
1379
        }
1380

1381
        // Array end
1382
        match parser.next_event()? {
2✔
1383
            Event::EndArray => println!("  ✅ EndArray OK"),
2✔
1384
            other => panic!("Expected EndArray, got: {:?}", other),
×
1385
        }
1386

1387
        // End document
1388
        match parser.next_event()? {
2✔
1389
            Event::EndDocument => println!("  ✅ EndDocument OK"),
2✔
1390
            other => panic!("Expected EndDocument, got: {:?}", other),
×
1391
        }
1392

1393
        println!("  🎉 SUCCESS with buffer size: {}", buffer_size);
2✔
1394
        Ok(())
2✔
1395
    }
3✔
1396

1397
    #[test]
1398
    fn test_minimal_buffer_simple_escape_1() {
1✔
1399
        // Buffer size 4 - clearly not enough
1400
        match test_simple_escape_with_buffer_size(4) {
1✔
1401
            Ok(()) => panic!("Expected failure with 4-byte buffer, but succeeded!"),
×
1402
            Err(e) => println!("Expected failure with 4-byte buffer: {:?}", e),
1✔
1403
        }
1404
    }
1✔
1405

1406
    #[test]
1407
    fn test_minimal_buffer_simple_escape_2() {
1✔
1408
        // Buffer size 12 - test if larger buffer avoids compaction bugs
1409
        test_simple_escape_with_buffer_size(12)
1✔
1410
            .expect("12-byte buffer should be sufficient for simple escape");
1✔
1411
    }
1✔
1412

1413
    #[test]
1414
    fn test_minimal_buffer_simple_escape_3() {
1✔
1415
        // Buffer size 24 - known working boundary from stress tests
1416
        test_simple_escape_with_buffer_size(24).expect("24-byte buffer should definitely work");
1✔
1417
    }
1✔
1418

1419
    #[test]
1420
    fn test_surrogate_pair_buffer_boundary_cases() {
1✔
1421
        // Test 7: Surrogate pair split across very small buffer chunks
1422
        let input7 = r#"["\uD801\uDC37"]"#;
1✔
1423
        let mut buffer7 = [0u8; 16]; // Small buffer
1✔
1424
        let reader7 = crate::chunk_reader::ChunkReader::new(input7.as_bytes(), 3); // Tiny chunks
1✔
1425
        let mut parser7 = StreamParser::<_, DefaultConfig>::with_config(reader7, &mut buffer7);
1✔
1426
        assert_eq!(parser7.next_event(), Ok(Event::StartArray));
1✔
1427
        match parser7.next_event() {
1✔
1428
            Ok(Event::String(s)) => {
1✔
1429
                let content = match s {
1✔
1430
                    crate::String::Borrowed(c) => c,
×
1431
                    crate::String::Unescaped(c) => c,
1✔
1432
                };
1433
                assert_eq!(content, "𐐷");
1✔
1434
            }
1435
            other => panic!(
×
1436
                "Expected String with surrogate pair across buffer boundary, got: {:?}",
×
1437
                other
1438
            ),
1439
        }
1440

1441
        // Test 8: Surrogate pair with small buffer (still needs minimum space)
1442
        let input8 = r#"["\uD801\uDC37"]"#;
1✔
1443
        let mut buffer8 = [0u8; 32]; // Small but sufficient buffer
1✔
1444
        let reader8 = crate::chunk_reader::ChunkReader::new(input8.as_bytes(), 6); // Split at surrogate boundary
1✔
1445
        let mut parser8 = StreamParser::<_, DefaultConfig>::with_config(reader8, &mut buffer8);
1✔
1446
        assert_eq!(parser8.next_event(), Ok(Event::StartArray));
1✔
1447
        match parser8.next_event() {
1✔
1448
            Ok(Event::String(s)) => {
1✔
1449
                let content = match s {
1✔
1450
                    crate::String::Borrowed(c) => c,
×
1451
                    crate::String::Unescaped(c) => c,
1✔
1452
                };
1453
                assert_eq!(content, "𐐷");
1✔
1454
            }
1455
            other => panic!(
×
1456
                "Expected String with surrogate pair at small buffer, got: {:?}",
×
1457
                other
1458
            ),
1459
        }
1460
    }
1✔
1461
}
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