use std::collections::BTreeMap;
use ijson::{ijson, IArray, INumber, IObject, IString, IValue};
#[test]
fn ivalue_serializes_to_json_text() {
let v = ijson!({
"null": null,
"bool": true,
"int": 42,
"float": 1.5,
"str": "hello",
"arr": [1, "two", false, null],
"obj": { "nested": 7 }
});
let text = serde_json::to_string(&v).unwrap();
let back: IValue = serde_json::from_str(&text).unwrap();
assert_eq!(v, back);
assert_eq!(
serde_json::to_string(&IString::intern("x")).unwrap(),
r#""x""#
);
let arr: IArray = vec![IValue::from(1), IValue::from(2)].into();
assert_eq!(serde_json::to_string(&arr).unwrap(), "[1,2]");
let mut obj = IObject::new();
obj.insert("k", IValue::from(1));
assert_eq!(serde_json::to_string(&obj).unwrap(), r#"{"k":1}"#);
assert_eq!(serde_json::to_string(&INumber::from(-5)).unwrap(), "-5");
}
#[test]
fn subtypes_deserialize_from_json_text() {
let s: IString = serde_json::from_str(r#""a\tb""#).unwrap(); assert_eq!(s.as_str(), "a\tb");
assert_eq!(
serde_json::from_str::<INumber>("42").unwrap(),
INumber::from(42)
);
assert_eq!(serde_json::from_str::<IArray>("[1,2,3]").unwrap().len(), 3);
let obj: IObject = serde_json::from_str(r#"{"a":1}"#).unwrap();
assert_eq!(obj["a"], IValue::from(1));
assert!(serde_json::from_str::<IString>("123").is_err());
assert!(serde_json::from_str::<INumber>(r#""x""#).is_err());
assert!(serde_json::from_str::<IArray>("123").is_err());
assert!(serde_json::from_str::<IObject>("123").is_err());
}
#[test]
fn ivalue_as_deserializer_for_every_type() {
let cases = vec![
IValue::NULL,
IValue::from(true),
IValue::from(42),
IValue::from(1.5),
IValue::from("s"),
ijson!([1, 2]),
ijson!({ "a": 1 }),
];
for v in cases {
let back: serde_json::Value = ijson::from_value(&v).unwrap();
assert_eq!(v, IValue::from(back));
}
assert_eq!(ijson::from_value::<i64>(&IValue::from(7)).unwrap(), 7);
assert_eq!(
ijson::from_value::<String>(&IValue::from("hi")).unwrap(),
"hi"
);
assert_eq!(
ijson::from_value::<Vec<i32>>(&ijson!([1, 2, 3])).unwrap(),
vec![1, 2, 3]
);
let map: BTreeMap<String, i32> = ijson::from_value(&ijson!({ "a": 1, "b": 2 })).unwrap();
assert_eq!(map["b"], 2);
}
#[derive(Debug, PartialEq, serde::Deserialize)]
enum Shape {
Unit,
Newtype(i32),
Tuple(i32, i32),
Struct { x: i32 },
}
#[test]
fn enum_deserialize_error_paths() {
assert!(ijson::from_value::<Shape>(&IValue::from(5)).is_err());
assert!(ijson::from_value::<Shape>(&ijson!({ "Tuple": 5 })).is_err()); assert!(ijson::from_value::<Shape>(&ijson!({ "Struct": [1, 2] })).is_err());
assert!(ijson::from_value::<Shape>(&ijson!({ "Unit": null, "extra": 1 })).is_err());
assert!(ijson::from_value::<Shape>(&IValue::from("Newtype")).is_err());
assert!(ijson::from_value::<Shape>(&IValue::from("Tuple")).is_err());
assert!(ijson::from_value::<Shape>(&IValue::from("Struct")).is_err());
assert_eq!(
ijson::from_value::<Shape>(&IValue::from("Unit")).unwrap(),
Shape::Unit
);
assert_eq!(
ijson::from_value::<Shape>(&ijson!({ "Unit": null })).unwrap(),
Shape::Unit
);
assert_eq!(
ijson::from_value::<Shape>(&ijson!({ "Newtype": 9 })).unwrap(),
Shape::Newtype(9)
);
assert_eq!(
ijson::from_value::<Shape>(&ijson!({ "Tuple": [1, 2] })).unwrap(),
Shape::Tuple(1, 2)
);
assert_eq!(
ijson::from_value::<Shape>(&ijson!({ "Struct": { "x": 3 } })).unwrap(),
Shape::Struct { x: 3 }
);
}
#[test]
fn type_mismatch_reports_the_found_type() {
assert!(ijson::from_value::<i32>(&IValue::NULL).is_err()); assert!(ijson::from_value::<i32>(&IValue::from(true)).is_err()); assert!(ijson::from_value::<i32>(&IValue::from("s")).is_err()); assert!(ijson::from_value::<i32>(&ijson!([1])).is_err()); assert!(ijson::from_value::<i32>(&ijson!({ "a": 1 })).is_err());
assert!(ijson::from_value::<String>(&IValue::from(-1)).is_err());
assert!(ijson::from_value::<String>(&IValue::from(1u64 << 63)).is_err());
assert!(ijson::from_value::<String>(&IValue::from(1.5)).is_err());
assert!(ijson::from_value::<BTreeMap<String, i32>>(&IValue::from(5)).is_err());
assert!(ijson::from_value::<()>(&IValue::from(5)).is_err());
}