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

kaidokert / picojson-rs / 16667763414

01 Aug 2025 06:10AM UTC coverage: 93.859% (-0.1%) from 94.008%
16667763414

Pull #77

github

web-flow
Merge 6293ac3f8 into 377ce19f7
Pull Request #77: Datasource intro

195 of 210 new or added lines in 6 files covered. (92.86%)

3 existing lines in 1 file now uncovered.

4983 of 5309 relevant lines covered (93.86%)

1108.24 hits per line

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

86.54
/picojson/src/slice_input_buffer.rs
1
// SPDX-License-Identifier: Apache-2.0
2

3
/// Error type for SliceInputBuffer operations.
4
#[derive(Debug, PartialEq)]
5
pub enum Error {
6
    /// Reached the end of input data.
7
    ReachedEnd,
8
    /// Invalid slice bounds provided.
9
    InvalidSliceBounds,
10
}
11

12
/// A buffer that manages input data and current parsing position.
13
/// This encapsulates the data slice and position that are always used together.
14
#[derive(Debug)]
15
pub struct SliceInputBuffer<'a> {
16
    data: &'a [u8],
17
    pos: usize,
18
}
19

20
pub trait InputBuffer {
21
    fn is_past_end(&self) -> bool;
22
    fn consume_byte(&mut self) -> Result<u8, Error>;
23
}
24

25
impl InputBuffer for SliceInputBuffer<'_> {
26
    fn is_past_end(&self) -> bool {
325✔
27
        self.pos > self.data.len()
325✔
28
    }
325✔
29
    fn consume_byte(&mut self) -> Result<u8, Error> {
2,203✔
30
        match self.data.get(self.pos) {
2,203✔
31
            Some(&byte) => {
2,171✔
32
                self.pos = self.pos.checked_add(1).ok_or(Error::InvalidSliceBounds)?;
2,171✔
33
                Ok(byte)
2,171✔
34
            }
35
            None => {
36
                self.pos = self.pos.checked_add(1).ok_or(Error::InvalidSliceBounds)?;
32✔
37
                Err(Error::ReachedEnd)
32✔
38
            }
39
        }
40
    }
2,203✔
41
}
42
impl<'a> SliceInputBuffer<'a> {
43
    pub fn current_pos(&self) -> usize {
372✔
44
        self.pos
372✔
45
    }
372✔
46
    /// Creates a new SliceInputBuffer with the given data.
47
    pub fn new(data: &'a [u8]) -> Self {
57✔
48
        Self { data, pos: 0 }
57✔
49
    }
57✔
50

51
    /// Gets a slice of the data from start to end positions, with bounds checking.
52
    pub fn slice(&self, start: usize, end: usize) -> Result<&'a [u8], Error> {
163✔
53
        self.data.get(start..end).ok_or(Error::InvalidSliceBounds)
163✔
54
    }
163✔
55

56
    /// Gets the length of the underlying data for bounds checking.
UNCOV
57
    pub fn data_len(&self) -> usize {
×
UNCOV
58
        self.data.len()
×
UNCOV
59
    }
×
60
}
61

62
#[cfg(test)]
63
mod tests {
64
    use super::*;
65

66
    #[test]
67
    fn test_buffer_boundary_behavior() {
1✔
68
        let data = b"abc"; // 3 bytes: positions 0, 1, 2 are valid
1✔
69
        let mut buffer = SliceInputBuffer::new(data);
1✔
70

71
        // Position 0: start, should have data
72
        assert_eq!(buffer.current_pos(), 0);
1✔
73
        assert!(!buffer.is_past_end(), "pos=0 should not be past end");
1✔
74
        assert_eq!(buffer.consume_byte(), Ok(b'a'));
1✔
75

76
        // Position 1: middle, should have data
77
        assert_eq!(buffer.current_pos(), 1);
1✔
78
        assert!(!buffer.is_past_end(), "pos=1 should not be past end");
1✔
79
        assert_eq!(buffer.consume_byte(), Ok(b'b'));
1✔
80

81
        // Position 2: last byte, should have data
82
        assert_eq!(buffer.current_pos(), 2);
1✔
83
        assert!(!buffer.is_past_end(), "pos=2 should not be past end");
1✔
84
        assert_eq!(buffer.consume_byte(), Ok(b'c'));
1✔
85

86
        // Position 3: exactly at end (pos == data.len()), no more data
87
        assert_eq!(buffer.current_pos(), 3);
1✔
88
        assert_eq!(
1✔
89
            buffer.current_pos(),
1✔
90
            data.len(),
1✔
91
            "pos should equal data.len()"
×
92
        );
93

94
        // INTENTIONAL DESIGN: Different semantics when pos == data.len()
95
        // - is_past_end() returns false (parser can still finish processing)
96
        // - consume_byte() returns Err (no more bytes to read)
97
        // This allows the tokenizer to complete final events (like EndObject)
98
        // even when no input bytes remain to be consumed
99
        assert!(
1✔
100
            !buffer.is_past_end(),
1✔
101
            "pos == data.len() should NOT be past end (allows tokenizer.finish())"
×
102
        );
103
        assert!(
1✔
104
            buffer.consume_byte().is_err(),
1✔
105
            "consume_byte() should fail when pos == data.len() (no bytes)"
×
106
        );
107

108
        // Position 4: past end (pos > data.len()), definitely error
109
        assert_eq!(buffer.current_pos(), 4);
1✔
110
        assert!(buffer.is_past_end(), "pos > data.len() should be past end");
1✔
111
        assert!(
1✔
112
            buffer.consume_byte().is_err(),
1✔
113
            "consume_byte() should fail when pos > data.len()"
×
114
        );
115
    }
1✔
116
}
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