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

kaidokert / picojson-rs / 16710654228

03 Aug 2025 11:34PM UTC coverage: 94.472% (-0.04%) from 94.51%
16710654228

push

github

web-flow
Introduce DataSource abstraction (#80)

156 of 163 new or added lines in 7 files covered. (95.71%)

70 existing lines in 7 files now uncovered.

4648 of 4920 relevant lines covered (94.47%)

664.44 hits per line

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

91.84
/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 {
323✔
27
        self.pos > self.data.len()
323✔
28
    }
323✔
29
    fn consume_byte(&mut self) -> Result<u8, Error> {
2,200✔
30
        match self.data.get(self.pos) {
2,200✔
31
            Some(&byte) => {
2,168✔
32
                self.pos = self.pos.checked_add(1).ok_or(Error::InvalidSliceBounds)?;
2,168✔
33
                Ok(byte)
2,168✔
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,200✔
41
}
42
impl<'a> SliceInputBuffer<'a> {
43
    pub fn current_pos(&self) -> usize {
370✔
44
        self.pos
370✔
45
    }
370✔
46
    /// Creates a new SliceInputBuffer with the given data.
47
    pub fn new(data: &'a [u8]) -> Self {
56✔
48
        Self { data, pos: 0 }
56✔
49
    }
56✔
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> {
162✔
53
        self.data.get(start..end).ok_or(Error::InvalidSliceBounds)
162✔
54
    }
162✔
55
}
56

57
#[cfg(test)]
58
mod tests {
59
    use super::*;
60

61
    #[test]
62
    fn test_buffer_boundary_behavior() {
1✔
63
        let data = b"abc"; // 3 bytes: positions 0, 1, 2 are valid
1✔
64
        let mut buffer = SliceInputBuffer::new(data);
1✔
65

66
        // Position 0: start, should have data
67
        assert_eq!(buffer.current_pos(), 0);
1✔
68
        assert!(!buffer.is_past_end(), "pos=0 should not be past end");
1✔
69
        assert_eq!(buffer.consume_byte(), Ok(b'a'));
1✔
70

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

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

81
        // Position 3: exactly at end (pos == data.len()), no more data
82
        assert_eq!(buffer.current_pos(), 3);
1✔
83
        assert_eq!(
1✔
84
            buffer.current_pos(),
1✔
85
            data.len(),
1✔
UNCOV
86
            "pos should equal data.len()"
×
87
        );
88

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

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