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

kaidokert / picojson-rs / 16296752393

15 Jul 2025 02:54PM UTC coverage: 91.544% (-2.2%) from 93.785%
16296752393

Pull #57

github

web-flow
Merge cdc45a9eb into 6be34a4b2
Pull Request #57: Even bigger refactor

481 of 649 new or added lines in 10 files covered. (74.11%)

17 existing lines in 5 files now uncovered.

4742 of 5180 relevant lines covered (91.54%)

739.86 hits per line

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

58.18
/picojson/src/parse_error.rs
1
// SPDX-License-Identifier: Apache-2.0
2

3
use crate::shared::UnexpectedState;
4
use crate::slice_input_buffer;
5
use crate::stream_buffer;
6

7
use crate::ujson;
8

9
/// Errors that can occur during JSON parsing
10
#[derive(Debug, PartialEq)]
11
pub enum ParseError {
12
    /// An error bubbled up from the underlying tokenizer.
13
    TokenizerError(ujson::Error),
14
    /// The provided scratch buffer was not large enough for an operation.
15
    ScratchBufferFull,
16
    /// A string slice was not valid UTF-8.
17
    InvalidUtf8(core::str::Utf8Error),
18
    /// A number string could not be parsed.
19
    InvalidNumber,
20
    /// The parser entered an unexpected internal state.
21
    Unexpected(UnexpectedState),
22
    /// End of input data.
23
    EndOfData,
24
    /// Invalid hex digits in Unicode escape sequence.
25
    InvalidUnicodeHex,
26
    /// Valid hex but invalid Unicode codepoint.
27
    InvalidUnicodeCodepoint,
28
    /// Invalid escape sequence character.
29
    InvalidEscapeSequence,
30
    /// Float encountered but float support is disabled and float-error is configured
31
    FloatNotAllowed,
32
    /// Error from the underlying reader (I/O error, not end-of-stream)
33
    ReaderError,
34
    /// Numeric overflow
35
    NumericOverflow,
36
}
37

38
impl From<slice_input_buffer::Error> for ParseError {
39
    fn from(err: slice_input_buffer::Error) -> Self {
×
40
        match err {
×
41
            slice_input_buffer::Error::ReachedEnd => ParseError::EndOfData,
×
42
            slice_input_buffer::Error::InvalidSliceBounds => {
43
                UnexpectedState::InvalidSliceBounds.into()
×
44
            }
45
        }
46
    }
×
47
}
48

49
impl From<stream_buffer::StreamBufferError> for ParseError {
50
    fn from(err: stream_buffer::StreamBufferError) -> Self {
×
51
        match err {
×
52
            stream_buffer::StreamBufferError::BufferFull => ParseError::ScratchBufferFull,
×
53
            stream_buffer::StreamBufferError::EndOfData => ParseError::EndOfData,
×
54
            stream_buffer::StreamBufferError::Unexpected => {
55
                ParseError::Unexpected(UnexpectedState::BufferCapacityExceeded)
×
56
            }
57
            stream_buffer::StreamBufferError::InvalidSliceBounds => {
58
                ParseError::Unexpected(UnexpectedState::InvalidSliceBounds)
×
59
            }
60
        }
61
    }
×
62
}
63

64
impl From<core::str::Utf8Error> for ParseError {
65
    fn from(err: core::str::Utf8Error) -> Self {
1✔
66
        ParseError::InvalidUtf8(err)
1✔
67
    }
1✔
68
}
69

70
impl From<UnexpectedState> for ParseError {
71
    fn from(info: UnexpectedState) -> Self {
5✔
72
        ParseError::Unexpected(info)
5✔
73
    }
5✔
74
}
75

76
impl core::fmt::Display for ParseError {
77
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
×
78
        match self {
×
NEW
79
            ParseError::TokenizerError(e) => write!(f, "{e}"),
×
NEW
80
            ParseError::InvalidUtf8(e) => write!(f, "Invalid UTF-8: {e}"),
×
NEW
81
            _ => write!(f, "{self:?}"),
×
82
        }
83
    }
×
84
}
85

86
#[cfg(test)]
87
mod tests {
88
    use super::*;
89

90
    #[test]
91
    fn test_error_constructors() {
1✔
92
        // Test state_mismatch error constructor
93
        let error: ParseError = UnexpectedState::StateMismatch.into();
1✔
94
        match error {
1✔
95
            ParseError::Unexpected(info) => {
1✔
96
                assert_eq!(info, UnexpectedState::StateMismatch);
1✔
97
            }
98
            _ => panic!("Expected UnexpectedState error"),
×
99
        }
100

101
        // Test invalid_unicode_length error constructor
102
        let error: ParseError = UnexpectedState::InvalidUnicodeEscape.into();
1✔
103
        match error {
1✔
104
            ParseError::Unexpected(info) => {
1✔
105
                assert_eq!(info, UnexpectedState::InvalidUnicodeEscape);
1✔
106
            }
107
            _ => panic!("Expected UnexpectedState error"),
×
108
        }
109

110
        // Test incomplete_unicode_escape error constructor
111
        let error: ParseError = UnexpectedState::InvalidUnicodeEscape.into();
1✔
112
        match error {
1✔
113
            ParseError::Unexpected(info) => {
1✔
114
                assert_eq!(info, UnexpectedState::InvalidUnicodeEscape);
1✔
115
            }
116
            _ => panic!("Expected UnexpectedState error"),
×
117
        }
118
    }
1✔
119

120
    #[test]
121
    fn test_utf8_error_conversion() {
1✔
122
        // Test From<Utf8Error> trait implementation
123
        use core::str;
124
        // Create a proper invalid UTF-8 sequence (lone continuation byte) dynamically
125
        // to avoid compile-time warning about static invalid UTF-8 literals
126
        let mut invalid_utf8_array = [0u8; 1];
1✔
127
        invalid_utf8_array[0] = 0b10000000u8; // Invalid UTF-8 - continuation byte without start
1✔
128
        let invalid_utf8 = &invalid_utf8_array;
1✔
129

130
        match str::from_utf8(invalid_utf8) {
1✔
131
            Err(utf8_error) => {
1✔
132
                let parse_error: ParseError = utf8_error.into();
1✔
133
                match parse_error {
1✔
134
                    ParseError::InvalidUtf8(_) => {
1✔
135
                        // Expected - conversion works correctly
1✔
136
                    }
1✔
137
                    _ => panic!("Expected InvalidUtf8 error"),
×
138
                }
139
            }
140
            Ok(_) => panic!("Expected UTF-8 validation to fail"),
×
141
        }
142
    }
1✔
143
}
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