use picojson::{Event, NumberResult, PullParser, SliceParser};
#[test]
#[cfg(feature = "int32")]
fn test_int32_overflow() {
let input = r#"{"value": 9999999999}"#; let mut scratch = [0u8; 1024];
let mut parser = SliceParser::with_buffer(input, &mut scratch);
assert!(matches!(parser.next_event(), Ok(Event::StartObject)));
assert!(matches!(parser.next_event(), Ok(Event::Key(_))));
match parser.next_event() {
Ok(Event::Number(num)) => {
assert_eq!(num.as_str(), "9999999999");
assert!(matches!(num.parsed(), NumberResult::IntegerOverflow));
assert_eq!(num.as_int(), None); }
other => panic!("Expected Number, got: {:?}", other),
}
}
#[test]
#[cfg(feature = "int64")]
fn test_int64_handles_large_numbers() {
let input = r#"{"value": 9999999999}"#; let mut scratch = [0u8; 1024];
let mut parser = SliceParser::with_buffer(input, &mut scratch);
assert!(matches!(parser.next_event(), Ok(Event::StartObject)));
assert!(matches!(parser.next_event(), Ok(Event::Key(_))));
match parser.next_event() {
Ok(Event::Number(num)) => {
assert_eq!(num.as_str(), "9999999999");
assert!(matches!(num.parsed(), NumberResult::Integer(9999999999)));
assert_eq!(num.as_int(), Some(9999999999));
}
other => panic!("Expected Number, got: {:?}", other),
}
}
#[test]
#[cfg(all(not(feature = "float"), feature = "float-error"))]
fn test_float_error_behavior() {
let input = r#"{"value": 3.14}"#;
let mut scratch = [0u8; 1024];
let mut parser = SliceParser::with_buffer(input, &mut scratch);
assert!(matches!(parser.next_event(), Ok(Event::StartObject)));
assert!(matches!(parser.next_event(), Ok(Event::Key(_))));
match parser.next_event() {
Err(picojson::ParseError::FloatNotAllowed) => {
}
other => panic!("Expected FloatNotAllowed error, got: {:?}", other),
}
}
#[test]
#[cfg(all(not(feature = "float"), feature = "float-truncate", feature = "int32"))]
fn test_float_truncate_to_i32() {
let input = r#"[1.7, 2.9, 3.1]"#;
let mut scratch = [0u8; 1024];
let mut parser = SliceParser::with_buffer(input, &mut scratch);
assert!(matches!(parser.next_event(), Ok(Event::StartArray)));
match parser.next_event() {
Ok(Event::Number(num)) => {
assert_eq!(num.as_str(), "1.7");
assert!(matches!(num.parsed(), NumberResult::FloatTruncated(1)));
assert_eq!(num.as_int(), Some(1));
}
other => panic!("Expected truncated Number(1), got: {:?}", other),
}
match parser.next_event() {
Ok(Event::Number(num)) => {
assert_eq!(num.as_str(), "2.9");
assert!(matches!(num.parsed(), NumberResult::FloatTruncated(2)));
assert_eq!(num.as_int(), Some(2));
}
other => panic!("Expected truncated Number(2), got: {:?}", other),
}
match parser.next_event() {
Ok(Event::Number(num)) => {
assert_eq!(num.as_str(), "3.1");
assert!(matches!(num.parsed(), NumberResult::FloatTruncated(3)));
assert_eq!(num.as_int(), Some(3));
}
other => panic!("Expected truncated Number(3), got: {:?}", other),
}
assert!(matches!(parser.next_event(), Ok(Event::EndArray)));
}
#[test]
#[cfg(all(
not(feature = "float"),
feature = "float-truncate",
not(feature = "int32")
))]
fn test_float_truncate_to_integer() {
let input = r#"[1.7, 2.9, 3.1]"#;
let mut scratch = [0u8; 1024];
let mut parser = SliceParser::with_buffer(input, &mut scratch);
assert!(matches!(parser.next_event(), Ok(Event::StartArray)));
match parser.next_event() {
Ok(Event::Number(num)) => {
assert_eq!(num.as_str(), "1.7");
assert!(matches!(num.parsed(), NumberResult::FloatTruncated(1)));
}
other => panic!("Expected truncated Number, got: {:?}", other),
}
}
#[test]
#[cfg(all(not(feature = "float"), feature = "float-truncate"))]
fn test_float_truncate_scientific_notation() {
let input = r#"{"value": 1.5e2}"#; let mut scratch = [0u8; 1024];
let mut parser = SliceParser::with_buffer(input, &mut scratch);
assert!(matches!(parser.next_event(), Ok(Event::StartObject)));
assert!(matches!(parser.next_event(), Ok(Event::Key(_))));
match parser.next_event() {
Err(picojson::ParseError::InvalidNumber) => {
}
other => panic!(
"Expected InvalidNumber error for scientific notation, got: {:?}",
other
),
}
}
#[test]
#[cfg(all(
not(feature = "float"),
feature = "int64",
not(any(
feature = "float-error",
feature = "float-skip",
feature = "float-truncate"
))
))]
fn test_default_float_disabled_behavior() {
let input = r#"{"value": 3.14}"#;
let mut scratch = [0u8; 1024];
let mut parser = SliceParser::with_buffer(input, &mut scratch);
assert!(matches!(parser.next_event(), Ok(Event::StartObject)));
assert!(matches!(parser.next_event(), Ok(Event::Key(_))));
match parser.next_event() {
Ok(Event::Number(num)) => {
assert_eq!(num.as_str(), "3.14");
assert!(matches!(num.parsed(), NumberResult::FloatDisabled));
assert_eq!(num.as_int(), None);
assert_eq!(num.as_str(), "3.14");
let manual_parse: Result<f64, _> = num.parse();
assert!(manual_parse.is_ok());
}
other => panic!("Expected Number with FloatDisabled, got: {:?}", other),
}
}
#[test]
#[cfg(feature = "int32")]
fn test_mixed_numbers_with_i32() {
let input = r#"{"small": 42, "large": 999999999999}"#; let mut scratch = [0u8; 1024];
let mut parser = SliceParser::with_buffer(input, &mut scratch);
assert!(matches!(parser.next_event(), Ok(Event::StartObject)));
assert!(matches!(parser.next_event(), Ok(Event::Key(_))));
match parser.next_event() {
Ok(Event::Number(num)) => {
assert_eq!(num.as_str(), "42");
assert!(matches!(num.parsed(), NumberResult::Integer(42)));
assert_eq!(num.as_int(), Some(42));
}
other => panic!("Expected Number(42), got: {:?}", other),
}
assert!(matches!(parser.next_event(), Ok(Event::Key(_))));
match parser.next_event() {
Ok(Event::Number(num)) => {
assert_eq!(num.as_str(), "999999999999");
assert!(matches!(num.parsed(), NumberResult::IntegerOverflow));
assert_eq!(num.as_int(), None);
assert_eq!(num.as_str(), "999999999999");
}
other => panic!("Expected Number with overflow, got: {:?}", other),
}
}
#[test]
#[cfg(all(feature = "int32", not(feature = "float"), feature = "float-error"))]
fn test_embedded_friendly_config() {
let input = r#"{"sensor": 42, "status": 1}"#;
let mut scratch = [0u8; 256]; let mut parser = SliceParser::with_buffer(input, &mut scratch);
assert!(matches!(parser.next_event(), Ok(Event::StartObject)));
assert!(matches!(parser.next_event(), Ok(Event::Key(_))));
match parser.next_event() {
Ok(Event::Number(num)) => {
assert_eq!(num.as_str(), "42");
assert!(matches!(num.parsed(), NumberResult::Integer(42i32)));
assert_eq!(num.as_int(), Some(42i32));
}
other => panic!("Expected Number(42), got: {:?}", other),
}
assert!(matches!(parser.next_event(), Ok(Event::Key(_))));
assert!(matches!(parser.next_event(), Ok(Event::Number(_))));
assert!(matches!(parser.next_event(), Ok(Event::EndObject)));
}