use crate::event_processor::{EscapeTiming, ParserCore};
use crate::parse_error::ParseError;
use crate::shared::Event;
use crate::stream_content_builder::StreamContentBuilder;
#[cfg(test)]
use crate::NumberResult;
use crate::{ujson, PullParser};
use ujson::{BitStackConfig, DefaultConfig};
pub trait Reader {
type Error;
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
}
pub struct StreamParser<'b, R: Reader, C: BitStackConfig = DefaultConfig> {
parser_core: ParserCore<C::Bucket, C::Counter>,
content_builder: StreamContentBuilder<'b, R>,
}
impl<'b, R: Reader> StreamParser<'b, R, DefaultConfig> {
pub fn new(reader: R, buffer: &'b mut [u8]) -> Self {
Self::with_config(reader, buffer)
}
}
impl<'b, R: Reader, C: BitStackConfig> StreamParser<'b, R, C> {
pub fn with_config(reader: R, buffer: &'b mut [u8]) -> Self {
Self {
parser_core: ParserCore::new(),
content_builder: StreamContentBuilder::new(buffer, reader),
}
}
}
impl<R: Reader, C: BitStackConfig> StreamParser<'_, R, C> {
fn next_event_impl(&mut self) -> Result<Event<'_, '_>, ParseError> {
self.parser_core.next_event_impl(
&mut self.content_builder,
EscapeTiming::OnEnd,
|provider, byte| {
provider.handle_byte_accumulation(byte)
},
)
}
}
impl<R: Reader, C: BitStackConfig> PullParser for StreamParser<'_, R, C> {
fn next_event(&mut self) -> Result<Event<'_, '_>, ParseError> {
if self.content_builder.is_finished() {
return Ok(Event::EndDocument);
}
self.content_builder.apply_unescaped_reset_if_queued();
self.next_event_impl()
}
}
#[cfg(test)]
mod tests {
use super::*;
pub struct SliceReader<'a> {
data: &'a [u8],
position: usize,
}
impl<'a> SliceReader<'a> {
pub fn new(data: &'a [u8]) -> Self {
Self { data, position: 0 }
}
}
impl Reader for SliceReader<'_> {
type Error = ();
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
let remaining = self.data.len().saturating_sub(self.position);
if remaining == 0 {
return Ok(0); }
let to_copy = remaining.min(buf.len());
let end_pos = self.position.saturating_add(to_copy);
if let (Some(dest), Some(src)) = (
buf.get_mut(..to_copy),
self.data.get(self.position..end_pos),
) {
dest.copy_from_slice(src);
self.position = end_pos;
Ok(to_copy)
} else {
Err(())
}
}
}
type TestStreamParser<'b> = StreamParser<'b, SliceReader<'static>>;
#[test]
fn test_direct_parser_simple_object() {
let json = b"{}";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
let event = parser.next_event().unwrap();
assert!(matches!(event, Event::StartObject));
let event = parser.next_event().unwrap();
assert!(matches!(event, Event::EndObject));
let event = parser.next_event().unwrap();
assert!(matches!(event, Event::EndDocument));
}
#[test]
fn test_direct_parser_simple_array() {
let json = b"[]";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
let event = parser.next_event().unwrap();
assert!(matches!(event, Event::StartArray));
let event = parser.next_event().unwrap();
assert!(matches!(event, Event::EndArray));
let event = parser.next_event().unwrap();
assert!(matches!(event, Event::EndDocument));
}
#[test]
fn test_direct_parser_simple_escape() {
let json = b"\"hello\\nworld\"";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
if let Event::String(json_string) = parser.next_event().unwrap() {
assert_eq!(json_string.as_str(), "hello\nworld");
} else {
panic!("Expected String event");
}
}
#[test]
fn test_pending_state_edge_cases() {
let json1 = br#"{"a": {"b": [{"c": 123}]}}"#;
let reader1 = SliceReader::new(json1);
let mut buffer1 = [0u8; 256];
let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
let mut events = Vec::new();
loop {
match parser1.next_event() {
Ok(Event::EndDocument) => break,
Ok(event) => events.push(format!("{:?}", event)),
Err(e) => panic!("Nested containers failed: {:?}", e),
}
}
assert!(events.len() >= 8);
let json2 = br#"[123, "string", true, null, 456]"#;
let reader2 = SliceReader::new(json2);
let mut buffer2 = [0u8; 256];
let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
let mut number_count = 0;
loop {
match parser2.next_event() {
Ok(Event::EndDocument) => break,
Ok(Event::Number(_)) => number_count += 1,
Ok(_) => {}
Err(e) => panic!("Mixed types failed: {:?}", e),
}
}
assert_eq!(number_count, 2);
let json3 = br#"[[], {}, [{}], {"empty": []}]"#;
let reader3 = SliceReader::new(json3);
let mut buffer3 = [0u8; 256];
let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
loop {
match parser3.next_event() {
Ok(Event::EndDocument) => break,
Ok(_) => {}
Err(e) => panic!("Empty containers failed: {:?}", e),
}
}
let json4 = br#"[1, 2, 3, 4, 5]"#;
let reader4 = SliceReader::new(json4);
let mut buffer4 = [0u8; 256];
let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
let mut consecutive_numbers = Vec::new();
loop {
match parser4.next_event() {
Ok(Event::EndDocument) => break,
Ok(Event::Number(n)) => consecutive_numbers.push(n.as_str().to_string()),
Ok(_) => {}
Err(e) => panic!("Consecutive numbers failed: {:?}", e),
}
}
assert_eq!(consecutive_numbers, vec!["1", "2", "3", "4", "5"]);
}
#[test]
fn test_error_recovery_with_pending_state() {
let invalid_json = br#"{"key": 123,"#; let reader = SliceReader::new(invalid_json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
loop {
match parser.next_event() {
Ok(Event::EndDocument) => break, Ok(_) => {}
Err(_) => break, }
}
}
#[test]
fn test_multiple_rapid_container_ends() {
let json1 = br#"[[[123]]]"#;
let reader1 = SliceReader::new(json1);
let mut buffer1 = [0u8; 256];
let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
let mut events1 = Vec::new();
loop {
match parser1.next_event() {
Ok(Event::EndDocument) => break,
Ok(event) => events1.push(format!("{:?}", event)),
Err(e) => panic!("Deeply nested arrays failed: {:?}", e),
}
}
assert_eq!(events1.len(), 7);
assert!(events1[3].contains("Number"));
assert_eq!(&events1[4], "EndArray");
assert_eq!(&events1[5], "EndArray");
assert_eq!(&events1[6], "EndArray");
let json2 = br#"{"a": [{"b": 456}]}"#;
let reader2 = SliceReader::new(json2);
let mut buffer2 = [0u8; 256];
let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
let mut events2 = Vec::new();
loop {
match parser2.next_event() {
Ok(Event::EndDocument) => break,
Ok(event) => events2.push(format!("{:?}", event)),
Err(e) => panic!("Mixed nested containers failed: {:?}", e),
}
}
assert!(events2.len() >= 8);
let json3 = br#"[123, [456, [789]]]"#;
let reader3 = SliceReader::new(json3);
let mut buffer3 = [0u8; 256];
let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
let mut number_count = 0;
let mut events3 = Vec::new();
loop {
match parser3.next_event() {
Ok(Event::EndDocument) => break,
Ok(Event::Number(n)) => {
number_count += 1;
events3.push(format!("Number({})", n.as_str()));
}
Ok(event) => events3.push(format!("{:?}", event)),
Err(e) => panic!("Multiple nested numbers failed: {:?}", e),
}
}
assert_eq!(number_count, 3); }
#[test]
fn test_pending_flag_priority() {
let json = br#"[{"key": 123}]"#;
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
let mut events = Vec::new();
loop {
match parser.next_event() {
Ok(Event::EndDocument) => break,
Ok(event) => events.push(format!("{:?}", event)),
Err(e) => panic!("Flag priority test failed: {:?}", e),
}
}
assert_eq!(events.len(), 6);
assert!(events[3].contains("Number"));
assert_eq!(&events[4], "EndObject");
assert_eq!(&events[5], "EndArray");
}
#[test]
fn test_direct_parser_array_of_strings() {
let json = b"[\"first\", \"second\"]";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
assert!(matches!(parser.next_event().unwrap(), Event::StartArray));
if let Event::String(s1) = parser.next_event().unwrap() {
assert_eq!(s1.as_str(), "first");
} else {
panic!("Expected String event");
}
if let Event::String(s2) = parser.next_event().unwrap() {
assert_eq!(s2.as_str(), "second");
} else {
panic!("Expected String event");
}
assert!(matches!(parser.next_event().unwrap(), Event::EndArray));
}
#[test]
fn test_direct_parser_object_with_keys() {
let json = b"{\"name\": \"value\", \"count\": \"42\"}";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
assert!(matches!(parser.next_event().unwrap(), Event::StartObject));
if let Event::Key(key1) = parser.next_event().unwrap() {
assert_eq!(key1.as_str(), "name");
} else {
panic!("Expected Key event");
}
if let Event::String(val1) = parser.next_event().unwrap() {
assert_eq!(val1.as_str(), "value");
} else {
panic!("Expected String event");
}
if let Event::Key(key2) = parser.next_event().unwrap() {
assert_eq!(key2.as_str(), "count");
} else {
panic!("Expected Key event");
}
if let Event::String(val2) = parser.next_event().unwrap() {
assert_eq!(val2.as_str(), "42");
} else {
panic!("Expected String event");
}
assert!(matches!(parser.next_event().unwrap(), Event::EndObject));
}
#[test]
fn test_direct_parser_multiple_escapes() {
let json = b"\"line1\\nline2\\ttab\\\"quote\"";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
if let Event::String(json_string) = parser.next_event().unwrap() {
let content = json_string.as_str();
let has_newline = content.contains('\n');
let has_tab = content.contains('\t');
let has_quote = content.contains('"');
assert!(has_newline, "Should contain actual newline character");
assert!(has_tab, "Should contain actual tab character");
assert!(has_quote, "Should contain actual quote character");
} else {
panic!("Expected String event");
}
}
#[test]
fn test_direct_parser_unicode_escape() {
let json = b"\"Hello \\u0041\\u03B1\""; let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
if let Event::String(json_string) = parser.next_event().unwrap() {
let content = json_string.as_str();
assert!(content.contains('A'));
} else {
panic!("Expected String event");
}
}
#[test]
fn test_direct_parser_boolean_true() {
let json = b"true";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
let event = parser.next_event().unwrap();
assert_eq!(event, Event::Bool(true));
let event = parser.next_event().unwrap();
assert_eq!(event, Event::EndDocument);
}
#[test]
fn test_direct_parser_boolean_false() {
let json = b"false";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
let event = parser.next_event().unwrap();
assert_eq!(event, Event::Bool(false));
let event = parser.next_event().unwrap();
assert_eq!(event, Event::EndDocument);
}
#[test]
fn test_direct_parser_null() {
let json = b"null";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
let event = parser.next_event().unwrap();
assert_eq!(event, Event::Null);
let event = parser.next_event().unwrap();
assert_eq!(event, Event::EndDocument);
}
#[test]
fn test_direct_parser_booleans_in_array() {
let json = b"[true, false, null]";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
assert_eq!(parser.next_event().unwrap(), Event::StartArray);
assert_eq!(parser.next_event().unwrap(), Event::Bool(true));
assert_eq!(parser.next_event().unwrap(), Event::Bool(false));
assert_eq!(parser.next_event().unwrap(), Event::Null);
assert_eq!(parser.next_event().unwrap(), Event::EndArray);
assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
}
#[test]
fn test_direct_parser_number_simple() {
let json = b"42";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
let event = parser.next_event().unwrap();
if let Event::Number(json_number) = event {
assert_eq!(json_number.as_str(), "42");
} else {
panic!("Expected Number event, got: {:?}", event);
}
let event = parser.next_event().unwrap();
assert_eq!(event, Event::EndDocument);
}
#[test]
fn test_direct_parser_number_negative() {
let json = b"-123";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
let event = parser.next_event().unwrap();
if let Event::Number(json_number) = event {
assert_eq!(json_number.as_str(), "-123");
} else {
panic!("Expected Number event, got: {:?}", event);
}
let event = parser.next_event().unwrap();
assert_eq!(event, Event::EndDocument);
}
#[test]
fn test_direct_parser_number_float() {
let json = b"3.14159";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
#[cfg(feature = "float-error")]
{
let result = parser.next_event();
assert!(
result.is_err(),
"Expected error for float with float-error configuration"
);
return;
}
#[cfg(not(feature = "float-error"))]
{
let event = parser.next_event().unwrap();
if let Event::Number(json_number) = event {
assert_eq!(json_number.as_str(), "3.14159");
} else {
panic!("Expected Number event, got: {:?}", event);
}
let event = parser.next_event().unwrap();
assert_eq!(event, Event::EndDocument);
}
}
#[test]
fn test_direct_parser_numbers_in_array() {
#[cfg(feature = "float-error")]
let json = b"[42, -7]"; #[cfg(not(feature = "float-error"))]
let json = b"[42, -7, 3.14]";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
assert_eq!(parser.next_event().unwrap(), Event::StartArray);
let event = parser.next_event().unwrap();
if let Event::Number(json_number) = event {
assert_eq!(json_number.as_str(), "42");
} else {
panic!("Expected Number event, got: {:?}", event);
}
let event = parser.next_event().unwrap();
if let Event::Number(json_number) = event {
assert_eq!(json_number.as_str(), "-7");
} else {
panic!("Expected Number event, got: {:?}", event);
}
#[cfg(not(feature = "float-error"))]
{
let event = parser.next_event().unwrap();
if let Event::Number(json_number) = event {
assert_eq!(json_number.as_str(), "3.14");
} else {
panic!("Expected Number event, got: {:?}", event);
}
}
assert_eq!(parser.next_event().unwrap(), Event::EndArray);
assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
}
#[test]
fn test_direct_parser_numbers_in_object() {
#[cfg(feature = "float-error")]
let json = b"{\"count\": 42, \"score\": -7}"; #[cfg(not(feature = "float-error"))]
let json = b"{\"count\": 42, \"score\": -7.5}";
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
assert_eq!(parser.next_event().unwrap(), Event::StartObject);
if let Event::Key(key1) = parser.next_event().unwrap() {
assert_eq!(key1.as_str(), "count");
} else {
panic!("Expected Key event");
}
if let Event::Number(val1) = parser.next_event().unwrap() {
assert_eq!(val1.as_str(), "42");
} else {
panic!("Expected Number event");
}
if let Event::Key(key2) = parser.next_event().unwrap() {
assert_eq!(key2.as_str(), "score");
} else {
panic!("Expected Key event");
}
if let Event::Number(val2) = parser.next_event().unwrap() {
#[cfg(feature = "float-error")]
assert_eq!(val2.as_str(), "-7");
#[cfg(not(feature = "float-error"))]
assert_eq!(val2.as_str(), "-7.5");
} else {
panic!("Expected Number event");
}
assert_eq!(parser.next_event().unwrap(), Event::EndObject);
assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
}
#[test]
fn test_direct_parser_no_float_configuration() {
let json = br#"{"integer": 42, "float": 3.14, "scientific": 1e3}"#;
let reader = SliceReader::new(json);
let mut buffer = [0u8; 256];
let mut parser = TestStreamParser::new(reader, &mut buffer);
assert_eq!(parser.next_event().unwrap(), Event::StartObject);
assert_eq!(
parser.next_event().unwrap(),
Event::Key(crate::String::Borrowed("integer"))
);
if let Event::Number(num) = parser.next_event().unwrap() {
assert_eq!(num.as_str(), "42");
match num.parsed() {
NumberResult::Integer(i) => assert_eq!(*i, 42),
_ => panic!("Expected integer parsing"),
}
} else {
panic!("Expected Number event");
}
assert_eq!(
parser.next_event().unwrap(),
Event::Key(crate::String::Borrowed("float"))
);
#[cfg(feature = "float-error")]
{
let result = parser.next_event();
assert!(
result.is_err(),
"Expected error for float with float-error configuration"
);
}
#[cfg(not(feature = "float-error"))]
{
if let Event::Number(num) = parser.next_event().unwrap() {
assert_eq!(num.as_str(), "3.14");
match num.parsed() {
#[cfg(not(feature = "float"))]
NumberResult::FloatDisabled => {
}
#[cfg(feature = "float")]
NumberResult::Float(f) => {
#[allow(clippy::approx_constant)]
{
assert!((f - 3.14).abs() < 0.01);
}
}
#[cfg(feature = "float-skip")]
NumberResult::FloatSkipped => {
}
#[cfg(feature = "float-truncate")]
NumberResult::FloatTruncated(i) => {
assert_eq!(*i, 3);
}
_ => panic!("Unexpected number parsing result for float"),
}
} else {
panic!("Expected Number event");
}
assert_eq!(
parser.next_event().unwrap(),
Event::Key(crate::String::Borrowed("scientific"))
);
#[cfg(feature = "float-truncate")]
{
let result = parser.next_event();
assert!(
result.is_err(),
"Expected error for scientific notation with float-truncate"
);
}
#[cfg(not(feature = "float-truncate"))]
{
if let Event::Number(num) = parser.next_event().unwrap() {
assert_eq!(num.as_str(), "1e3");
match num.parsed() {
#[cfg(not(feature = "float"))]
NumberResult::FloatDisabled => {
}
#[cfg(feature = "float-skip")]
NumberResult::FloatSkipped => {
}
#[cfg(feature = "float")]
NumberResult::Float(f) => {
assert!((f - 1000.0).abs() < f64::EPSILON);
}
_ => panic!("Unexpected number parsing result for scientific notation"),
}
} else {
panic!("Expected Number event");
}
assert_eq!(parser.next_event().unwrap(), Event::EndObject);
assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
}
}
}
#[test]
fn test_number_parsing_delimiter_exclusion() {
let json1 = b"[123]";
let reader1 = SliceReader::new(json1);
let mut buffer1 = [0u8; 256];
let mut parser1 = TestStreamParser::new(reader1, &mut buffer1);
assert!(matches!(parser1.next_event().unwrap(), Event::StartArray));
if let Event::Number(num) = parser1.next_event().unwrap() {
assert_eq!(
num.as_str(),
"123",
"Number should not include trailing delimiter ']'"
);
} else {
panic!("Expected Number event");
}
assert!(matches!(parser1.next_event().unwrap(), Event::EndArray));
let json2 = b"{\"key\":456}";
let reader2 = SliceReader::new(json2);
let mut buffer2 = [0u8; 256];
let mut parser2 = TestStreamParser::new(reader2, &mut buffer2);
assert!(matches!(parser2.next_event().unwrap(), Event::StartObject));
assert!(matches!(parser2.next_event().unwrap(), Event::Key(_)));
if let Event::Number(num) = parser2.next_event().unwrap() {
assert_eq!(
num.as_str(),
"456",
"Number should not include trailing delimiter '}}'"
);
} else {
panic!("Expected Number event");
}
assert!(matches!(parser2.next_event().unwrap(), Event::EndObject));
let json3 = b"[789,10]";
let reader3 = SliceReader::new(json3);
let mut buffer3 = [0u8; 256];
let mut parser3 = TestStreamParser::new(reader3, &mut buffer3);
assert!(matches!(parser3.next_event().unwrap(), Event::StartArray));
if let Event::Number(num1) = parser3.next_event().unwrap() {
assert_eq!(
num1.as_str(),
"789",
"First number should not include trailing delimiter ','"
);
} else {
panic!("Expected first Number event");
}
if let Event::Number(num2) = parser3.next_event().unwrap() {
assert_eq!(
num2.as_str(),
"10",
"Second number should not include trailing delimiter ']'"
);
} else {
panic!("Expected second Number event");
}
assert!(matches!(parser3.next_event().unwrap(), Event::EndArray));
let json4 = b"{\"a\":11,\"b\":22}";
let reader4 = SliceReader::new(json4);
let mut buffer4 = [0u8; 256];
let mut parser4 = TestStreamParser::new(reader4, &mut buffer4);
assert!(matches!(parser4.next_event().unwrap(), Event::StartObject));
assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
if let Event::Number(num1) = parser4.next_event().unwrap() {
assert_eq!(
num1.as_str(),
"11",
"First number should not include trailing delimiter ','"
);
} else {
panic!("Expected first Number event");
}
assert!(matches!(parser4.next_event().unwrap(), Event::Key(_)));
if let Event::Number(num2) = parser4.next_event().unwrap() {
assert_eq!(
num2.as_str(),
"22",
"Second number should not include trailing delimiter '}}'"
);
} else {
panic!("Expected second Number event");
}
assert!(matches!(parser4.next_event().unwrap(), Event::EndObject));
let json5 = b"999";
let reader5 = SliceReader::new(json5);
let mut buffer5 = [0u8; 256];
let mut parser5 = TestStreamParser::new(reader5, &mut buffer5);
if let Event::Number(num) = parser5.next_event().unwrap() {
assert_eq!(
num.as_str(),
"999",
"Standalone number should include full content"
);
} else {
panic!("Expected Number event");
}
assert!(matches!(parser5.next_event().unwrap(), Event::EndDocument));
let json6 = b"[-42,33]";
let reader6 = SliceReader::new(json6);
let mut buffer6 = [0u8; 256];
let mut parser6 = TestStreamParser::new(reader6, &mut buffer6);
assert!(matches!(parser6.next_event().unwrap(), Event::StartArray));
if let Event::Number(num1) = parser6.next_event().unwrap() {
assert_eq!(
num1.as_str(),
"-42",
"Negative number should not include trailing delimiter ','"
);
} else {
panic!("Expected first Number event");
}
if let Event::Number(num2) = parser6.next_event().unwrap() {
assert_eq!(
num2.as_str(),
"33",
"Second number should not include trailing delimiter ']'"
);
} else {
panic!("Expected second Number event");
}
assert!(matches!(parser6.next_event().unwrap(), Event::EndArray));
#[cfg(not(feature = "float-error"))]
{
let json7 = b"[3.14,2.71]";
let reader7 = SliceReader::new(json7);
let mut buffer7 = [0u8; 256];
let mut parser7 = TestStreamParser::new(reader7, &mut buffer7);
assert!(matches!(parser7.next_event().unwrap(), Event::StartArray));
if let Event::Number(num1) = parser7.next_event().unwrap() {
assert_eq!(
num1.as_str(),
"3.14",
"Decimal number should not include trailing delimiter ','"
);
} else {
panic!("Expected first Number event");
}
if let Event::Number(num2) = parser7.next_event().unwrap() {
assert_eq!(
num2.as_str(),
"2.71",
"Second decimal number should not include trailing delimiter ']'"
);
} else {
panic!("Expected second Number event");
}
assert!(matches!(parser7.next_event().unwrap(), Event::EndArray));
}
}
#[test]
fn test_escape_buffer_functions() {
let json_stream = br#"{"escaped": "test\nstring"}"#;
let mut buffer = [0u8; 1024];
let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
assert_eq!(parser.next_event().unwrap(), Event::StartObject);
assert_eq!(
parser.next_event().unwrap(),
Event::Key(crate::String::Borrowed("escaped"))
);
if let Event::String(s) = parser.next_event().unwrap() {
assert_eq!(s.as_ref(), "test\nstring"); } else {
panic!("Expected String event with escape sequence");
}
assert_eq!(parser.next_event().unwrap(), Event::EndObject);
assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
}
#[test]
fn test_slice_reader_constructor() {
let data = b"test data";
let reader = SliceReader::new(data);
assert_eq!(reader.data, data);
assert_eq!(reader.position, 0);
}
#[test]
fn test_complex_escape_sequences() {
let json_stream = br#"{"multi": "line1\nline2\ttab\r\n"}"#;
let mut buffer = [0u8; 1024];
let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
assert_eq!(parser.next_event().unwrap(), Event::StartObject);
assert_eq!(
parser.next_event().unwrap(),
Event::Key(crate::String::Borrowed("multi"))
);
if let Event::String(s) = parser.next_event().unwrap() {
assert_eq!(s.as_ref(), "line1\nline2\ttab\r\n");
} else {
panic!("Expected String event");
}
assert_eq!(parser.next_event().unwrap(), Event::EndObject);
assert_eq!(parser.next_event().unwrap(), Event::EndDocument);
}
fn test_simple_escape_with_buffer_size(buffer_size: usize) -> Result<(), ParseError> {
let json_stream = br#"["hello\\"]"#;
let mut buffer = vec![0u8; buffer_size];
let mut parser = StreamParser::new(SliceReader::new(json_stream), &mut buffer);
assert!(matches!(parser.next_event()?, Event::StartArray));
assert!(matches!(parser.next_event()?, Event::String(s) if s.as_str() == "hello\\"));
assert!(matches!(parser.next_event()?, Event::EndArray));
assert!(matches!(parser.next_event()?, Event::EndDocument));
Ok(())
}
#[test]
fn test_minimal_buffer_simple_escape_1() {
assert!(matches!(
test_simple_escape_with_buffer_size(4),
Err(ParseError::InputBufferFull)
));
}
#[test]
fn test_minimal_buffer_simple_escape_2() {
test_simple_escape_with_buffer_size(12)
.expect("12-byte buffer should be sufficient for simple escape");
}
#[test]
fn test_minimal_buffer_simple_escape_3() {
test_simple_escape_with_buffer_size(24).expect("24-byte buffer should definitely work");
}
#[test]
fn test_surrogate_pair_buffer_boundary_cases() {
let input7 = r#"["\uD801\uDC37"]"#;
let mut buffer7 = [0u8; 16]; let reader7 = crate::chunk_reader::ChunkReader::new(input7.as_bytes(), 3); let mut parser7 = StreamParser::<_, DefaultConfig>::with_config(reader7, &mut buffer7);
assert_eq!(parser7.next_event(), Ok(Event::StartArray));
match parser7.next_event() {
Ok(Event::String(s)) => {
let content = match s {
crate::String::Borrowed(c) => c,
crate::String::Unescaped(c) => c,
};
assert_eq!(content, "𐐷");
}
other => panic!(
"Expected String with surrogate pair across buffer boundary, got: {:?}",
other
),
}
let input8 = r#"["\uD801\uDC37"]"#;
let mut buffer8 = [0u8; 32]; let reader8 = crate::chunk_reader::ChunkReader::new(input8.as_bytes(), 6); let mut parser8 = StreamParser::<_, DefaultConfig>::with_config(reader8, &mut buffer8);
assert_eq!(parser8.next_event(), Ok(Event::StartArray));
match parser8.next_event() {
Ok(Event::String(s)) => {
let content = match s {
crate::String::Borrowed(c) => c,
crate::String::Unescaped(c) => c,
};
assert_eq!(content, "𐐷");
}
other => panic!(
"Expected String with surrogate pair at small buffer, got: {:?}",
other
),
}
}
}