2020-07-03 11:19:55 +02:00
|
|
|
#![cfg(feature = "serde")]
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
use rhai::{
|
|
|
|
serde::{from_dynamic, to_dynamic},
|
2021-03-05 16:56:00 +01:00
|
|
|
Dynamic, Engine, EvalAltResult, ImmutableString, INT,
|
2020-10-10 08:15:23 +02:00
|
|
|
};
|
2020-07-03 16:42:56 +02:00
|
|
|
use serde::{Deserialize, Serialize};
|
2022-05-23 16:40:49 +02:00
|
|
|
use serde_json::json;
|
2020-07-03 11:19:55 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
use rhai::Array;
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
use rhai::Map;
|
2021-04-06 17:18:28 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
use rhai::FLOAT;
|
2022-01-15 04:26:43 +01:00
|
|
|
#[cfg(feature = "no_float")]
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
use rust_decimal::Decimal;
|
2020-07-03 11:19:55 +02:00
|
|
|
|
|
|
|
#[test]
|
2020-07-03 16:42:56 +02:00
|
|
|
fn test_serde_ser_primary_types() -> Result<(), Box<EvalAltResult>> {
|
2020-07-06 15:52:07 +02:00
|
|
|
assert!(to_dynamic(42_u64)?.is::<INT>());
|
|
|
|
assert!(to_dynamic(u64::MAX)?.is::<u64>());
|
|
|
|
assert!(to_dynamic(42 as INT)?.is::<INT>());
|
|
|
|
assert!(to_dynamic(true)?.is::<bool>());
|
|
|
|
assert!(to_dynamic(())?.is::<()>());
|
2020-07-03 11:19:55 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
{
|
2020-07-06 15:52:07 +02:00
|
|
|
assert!(to_dynamic(123.456_f64)?.is::<f64>());
|
|
|
|
assert!(to_dynamic(123.456_f32)?.is::<f32>());
|
2020-07-03 16:42:56 +02:00
|
|
|
}
|
|
|
|
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "no_float")]
|
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
{
|
|
|
|
assert!(to_dynamic(123.456_f64)?.is::<Decimal>());
|
|
|
|
assert!(to_dynamic(123.456_f32)?.is::<Decimal>());
|
|
|
|
}
|
|
|
|
|
2020-07-06 15:52:07 +02:00
|
|
|
assert!(to_dynamic("hello".to_string())?.is::<String>());
|
2020-07-03 16:42:56 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-07-05 05:35:50 +02:00
|
|
|
#[test]
|
|
|
|
fn test_serde_ser_integer_types() -> Result<(), Box<EvalAltResult>> {
|
2020-07-06 15:52:07 +02:00
|
|
|
assert!(to_dynamic(42_i8)?.is::<INT>());
|
|
|
|
assert!(to_dynamic(42_i16)?.is::<INT>());
|
|
|
|
assert!(to_dynamic(42_i32)?.is::<INT>());
|
|
|
|
assert!(to_dynamic(42_i64)?.is::<INT>());
|
|
|
|
assert!(to_dynamic(42_u8)?.is::<INT>());
|
|
|
|
assert!(to_dynamic(42_u16)?.is::<INT>());
|
|
|
|
assert!(to_dynamic(42_u32)?.is::<INT>());
|
|
|
|
assert!(to_dynamic(42_u64)?.is::<INT>());
|
2020-07-05 05:35:50 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-07-03 16:42:56 +02:00
|
|
|
#[test]
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
fn test_serde_ser_array() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
let arr: Vec<INT> = vec![123, 456, 42, 999];
|
|
|
|
|
|
|
|
let d = to_dynamic(arr)?;
|
|
|
|
assert!(d.is::<Array>());
|
2020-07-06 15:52:07 +02:00
|
|
|
assert_eq!(4, d.cast::<Array>().len());
|
2020-07-03 16:42:56 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
fn test_serde_ser_struct() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
#[derive(Debug, Serialize, PartialEq)]
|
|
|
|
struct Hello {
|
|
|
|
a: INT,
|
|
|
|
b: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, PartialEq)]
|
|
|
|
struct Test {
|
|
|
|
int: u32,
|
|
|
|
seq: Vec<String>,
|
|
|
|
obj: Hello,
|
|
|
|
}
|
|
|
|
|
|
|
|
let x = Test {
|
|
|
|
int: 42,
|
|
|
|
seq: vec!["hello".into(), "kitty".into(), "world".into()],
|
|
|
|
obj: Hello { a: 123, b: true },
|
|
|
|
};
|
|
|
|
|
|
|
|
let d = to_dynamic(x)?;
|
|
|
|
|
|
|
|
assert!(d.is::<Map>());
|
|
|
|
|
|
|
|
let mut map = d.cast::<Map>();
|
2020-07-06 15:52:07 +02:00
|
|
|
let obj = map.remove("obj").unwrap().cast::<Map>();
|
2021-03-05 16:41:20 +01:00
|
|
|
let mut seq = map.remove("seq").unwrap().cast::<Array>();
|
2020-07-03 16:42:56 +02:00
|
|
|
|
2020-07-06 15:52:07 +02:00
|
|
|
assert_eq!(Ok(123), obj["a"].as_int());
|
|
|
|
assert!(obj["b"].as_bool().unwrap());
|
|
|
|
assert_eq!(Ok(42), map["int"].as_int());
|
2020-07-03 16:42:56 +02:00
|
|
|
assert_eq!(seq.len(), 3);
|
2021-07-24 10:24:59 +02:00
|
|
|
assert_eq!("kitty", seq.remove(1).into_string().unwrap());
|
2020-07-03 16:42:56 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-07-06 10:11:54 +02:00
|
|
|
#[test]
|
|
|
|
fn test_serde_ser_unit_enum() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
#[derive(Serialize)]
|
|
|
|
enum MyEnum {
|
|
|
|
VariantFoo,
|
|
|
|
VariantBar,
|
|
|
|
}
|
|
|
|
|
|
|
|
let d = to_dynamic(MyEnum::VariantFoo)?;
|
2021-07-24 10:24:59 +02:00
|
|
|
assert_eq!("VariantFoo", d.into_string().unwrap());
|
2020-07-06 10:11:54 +02:00
|
|
|
|
|
|
|
let d = to_dynamic(MyEnum::VariantBar)?;
|
2021-07-24 10:24:59 +02:00
|
|
|
assert_eq!("VariantBar", d.into_string().unwrap());
|
2020-07-06 10:11:54 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
fn test_serde_ser_externally_tagged_enum() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
#[derive(Serialize)]
|
|
|
|
enum MyEnum {
|
|
|
|
VariantUnit,
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
VariantUnitTuple(),
|
|
|
|
VariantNewtype(i32),
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
VariantTuple(i32, i32),
|
|
|
|
VariantEmptyStruct {},
|
|
|
|
VariantStruct {
|
|
|
|
a: i32,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2021-03-05 16:41:20 +01:00
|
|
|
assert_eq!(
|
|
|
|
"VariantUnit",
|
|
|
|
to_dynamic(MyEnum::VariantUnit)?
|
2021-07-24 10:24:59 +02:00
|
|
|
.into_immutable_string()
|
2021-03-05 16:41:20 +01:00
|
|
|
.unwrap()
|
|
|
|
.as_str()
|
|
|
|
);
|
2020-07-06 10:11:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
{
|
2020-07-06 15:52:07 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantUnitTuple())?.cast::<Map>();
|
2020-07-06 10:11:54 +02:00
|
|
|
let content = map.remove("VariantUnitTuple").unwrap().cast::<Array>();
|
|
|
|
assert!(map.is_empty());
|
|
|
|
assert!(content.is_empty());
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantNewtype(123))?.cast::<Map>();
|
|
|
|
let content = map.remove("VariantNewtype").unwrap();
|
|
|
|
assert!(map.is_empty());
|
|
|
|
assert_eq!(Ok(123), content.as_int());
|
2020-07-06 10:11:54 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
{
|
2020-07-06 15:52:07 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantTuple(123, 456))?.cast::<Map>();
|
2020-07-06 10:11:54 +02:00
|
|
|
let content = map.remove("VariantTuple").unwrap().cast::<Array>();
|
|
|
|
assert!(map.is_empty());
|
|
|
|
assert_eq!(2, content.len());
|
|
|
|
assert_eq!(Ok(123), content[0].as_int());
|
|
|
|
assert_eq!(Ok(456), content[1].as_int());
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantEmptyStruct {})?.cast::<Map>();
|
|
|
|
let map_inner = map.remove("VariantEmptyStruct").unwrap().cast::<Map>();
|
|
|
|
assert!(map.is_empty());
|
|
|
|
assert!(map_inner.is_empty());
|
2020-07-06 10:11:54 +02:00
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantStruct { a: 123 })?.cast::<Map>();
|
|
|
|
let mut map_inner = map.remove("VariantStruct").unwrap().cast::<Map>();
|
|
|
|
assert!(map.is_empty());
|
|
|
|
assert_eq!(Ok(123), map_inner.remove("a").unwrap().as_int());
|
|
|
|
assert!(map_inner.is_empty());
|
2020-07-06 10:11:54 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
fn test_serde_ser_internally_tagged_enum() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
#[derive(Serialize)]
|
|
|
|
#[serde(tag = "tag")]
|
|
|
|
enum MyEnum {
|
|
|
|
VariantEmptyStruct {},
|
|
|
|
VariantStruct { a: i32 },
|
|
|
|
}
|
|
|
|
|
2020-07-06 15:52:07 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantEmptyStruct {})?.cast::<Map>();
|
2020-07-06 10:11:54 +02:00
|
|
|
assert_eq!(
|
2021-03-05 16:41:20 +01:00
|
|
|
"VariantEmptyStruct",
|
|
|
|
map.remove("tag")
|
|
|
|
.unwrap()
|
2021-07-24 10:24:59 +02:00
|
|
|
.into_immutable_string()
|
2021-03-05 16:41:20 +01:00
|
|
|
.unwrap()
|
|
|
|
.as_str()
|
2020-07-06 10:11:54 +02:00
|
|
|
);
|
|
|
|
assert!(map.is_empty());
|
|
|
|
|
2020-07-06 15:52:07 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantStruct { a: 123 })?.cast::<Map>();
|
2021-03-05 16:41:20 +01:00
|
|
|
assert_eq!(
|
|
|
|
"VariantStruct",
|
|
|
|
map.remove("tag")
|
|
|
|
.unwrap()
|
2021-07-24 10:24:59 +02:00
|
|
|
.into_immutable_string()
|
2021-03-05 16:41:20 +01:00
|
|
|
.unwrap()
|
|
|
|
.as_str()
|
|
|
|
);
|
2020-07-06 10:11:54 +02:00
|
|
|
assert_eq!(Ok(123), map.remove("a").unwrap().as_int());
|
|
|
|
assert!(map.is_empty());
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
fn test_serde_ser_adjacently_tagged_enum() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
#[derive(Serialize)]
|
|
|
|
#[serde(tag = "tag", content = "content")]
|
|
|
|
enum MyEnum {
|
|
|
|
VariantUnit,
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
VariantUnitTuple(),
|
|
|
|
VariantNewtype(i32),
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
VariantTuple(i32, i32),
|
|
|
|
VariantEmptyStruct {},
|
|
|
|
VariantStruct {
|
|
|
|
a: i32,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantUnit)?.cast::<Map>();
|
2021-03-05 16:41:20 +01:00
|
|
|
assert_eq!(
|
|
|
|
"VariantUnit",
|
|
|
|
map.remove("tag")
|
|
|
|
.unwrap()
|
2021-07-24 10:24:59 +02:00
|
|
|
.into_immutable_string()
|
2021-03-05 16:41:20 +01:00
|
|
|
.unwrap()
|
|
|
|
.as_str()
|
|
|
|
);
|
2020-10-10 08:15:23 +02:00
|
|
|
assert!(map.is_empty());
|
2020-07-06 10:11:54 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
{
|
2020-07-06 15:52:07 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantUnitTuple())?.cast::<Map>();
|
2021-03-05 16:41:20 +01:00
|
|
|
assert_eq!(
|
|
|
|
"VariantUnitTuple",
|
|
|
|
map.remove("tag")
|
|
|
|
.unwrap()
|
2021-07-24 10:24:59 +02:00
|
|
|
.into_immutable_string()
|
2021-03-05 16:41:20 +01:00
|
|
|
.unwrap()
|
|
|
|
.as_str()
|
|
|
|
);
|
2020-07-06 10:11:54 +02:00
|
|
|
let content = map.remove("content").unwrap().cast::<Array>();
|
|
|
|
assert!(map.is_empty());
|
|
|
|
assert!(content.is_empty());
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantNewtype(123))?.cast::<Map>();
|
2021-03-05 16:41:20 +01:00
|
|
|
assert_eq!(
|
|
|
|
"VariantNewtype",
|
|
|
|
map.remove("tag")
|
|
|
|
.unwrap()
|
2021-07-24 10:24:59 +02:00
|
|
|
.into_immutable_string()
|
2021-03-05 16:41:20 +01:00
|
|
|
.unwrap()
|
|
|
|
.as_str()
|
|
|
|
);
|
2020-10-10 08:15:23 +02:00
|
|
|
let content = map.remove("content").unwrap();
|
|
|
|
assert!(map.is_empty());
|
|
|
|
assert_eq!(Ok(123), content.as_int());
|
2020-07-06 10:11:54 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
{
|
2020-07-06 15:52:07 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantTuple(123, 456))?.cast::<Map>();
|
2021-03-05 16:41:20 +01:00
|
|
|
assert_eq!(
|
|
|
|
"VariantTuple",
|
|
|
|
map.remove("tag")
|
|
|
|
.unwrap()
|
2021-07-24 10:24:59 +02:00
|
|
|
.into_immutable_string()
|
2021-03-05 16:41:20 +01:00
|
|
|
.unwrap()
|
|
|
|
.as_str()
|
|
|
|
);
|
2020-07-06 10:11:54 +02:00
|
|
|
let content = map.remove("content").unwrap().cast::<Array>();
|
|
|
|
assert!(map.is_empty());
|
|
|
|
assert_eq!(2, content.len());
|
|
|
|
assert_eq!(Ok(123), content[0].as_int());
|
|
|
|
assert_eq!(Ok(456), content[1].as_int());
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantEmptyStruct {})?.cast::<Map>();
|
|
|
|
assert_eq!(
|
2021-03-05 16:41:20 +01:00
|
|
|
"VariantEmptyStruct",
|
|
|
|
map.remove("tag")
|
|
|
|
.unwrap()
|
2021-07-24 10:24:59 +02:00
|
|
|
.into_immutable_string()
|
2021-03-05 16:41:20 +01:00
|
|
|
.unwrap()
|
|
|
|
.as_str()
|
2020-10-10 08:15:23 +02:00
|
|
|
);
|
|
|
|
let map_inner = map.remove("content").unwrap().cast::<Map>();
|
|
|
|
assert!(map.is_empty());
|
|
|
|
assert!(map_inner.is_empty());
|
2020-07-06 10:11:54 +02:00
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantStruct { a: 123 })?.cast::<Map>();
|
2021-03-05 16:41:20 +01:00
|
|
|
assert_eq!(
|
|
|
|
"VariantStruct",
|
2021-07-24 10:24:59 +02:00
|
|
|
map.remove("tag").unwrap().into_string().unwrap()
|
2021-03-05 16:41:20 +01:00
|
|
|
);
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map_inner = map.remove("content").unwrap().cast::<Map>();
|
|
|
|
assert!(map.is_empty());
|
|
|
|
assert_eq!(Ok(123), map_inner.remove("a").unwrap().as_int());
|
|
|
|
assert!(map_inner.is_empty());
|
2020-07-06 10:11:54 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
fn test_serde_ser_untagged_enum() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
#[derive(Serialize)]
|
|
|
|
#[serde(untagged)]
|
|
|
|
enum MyEnum {
|
|
|
|
VariantEmptyStruct {},
|
|
|
|
VariantStruct1 { a: i32 },
|
|
|
|
VariantStruct2 { b: i32 },
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let map = to_dynamic(MyEnum::VariantEmptyStruct {})?.cast::<Map>();
|
|
|
|
assert!(map.is_empty());
|
2020-07-06 10:11:54 +02:00
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantStruct1 { a: 123 })?.cast::<Map>();
|
|
|
|
assert_eq!(Ok(123), map.remove("a").unwrap().as_int());
|
|
|
|
assert!(map.is_empty());
|
2020-07-06 10:11:54 +02:00
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map = to_dynamic(MyEnum::VariantStruct2 { b: 123 })?.cast::<Map>();
|
|
|
|
assert_eq!(Ok(123), map.remove("b").unwrap().as_int());
|
|
|
|
assert!(map.is_empty());
|
2020-07-06 10:11:54 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-07-03 16:42:56 +02:00
|
|
|
#[test]
|
|
|
|
fn test_serde_de_primary_types() -> Result<(), Box<EvalAltResult>> {
|
2021-01-18 03:30:58 +01:00
|
|
|
assert_eq!(42, from_dynamic::<u16>(&Dynamic::from(42_u16))?);
|
|
|
|
assert_eq!(42, from_dynamic::<INT>(&(42 as INT).into())?);
|
|
|
|
assert_eq!(true, from_dynamic::<bool>(&true.into())?);
|
|
|
|
assert_eq!((), from_dynamic::<()>(&().into())?);
|
2020-07-03 16:42:56 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
{
|
2021-04-06 17:18:28 +02:00
|
|
|
assert_eq!(123.456, from_dynamic::<FLOAT>(&123.456.into())?);
|
2021-01-18 03:30:58 +01:00
|
|
|
assert_eq!(123.456, from_dynamic::<f32>(&Dynamic::from(123.456_f32))?);
|
2020-07-03 11:19:55 +02:00
|
|
|
}
|
|
|
|
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "no_float")]
|
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
{
|
|
|
|
let d: Dynamic = Decimal::from_str("123.456").unwrap().into();
|
|
|
|
|
|
|
|
assert_eq!(123.456, from_dynamic::<f64>(&d)?);
|
|
|
|
assert_eq!(123.456, from_dynamic::<f32>(&d)?);
|
|
|
|
}
|
|
|
|
|
2020-07-03 11:19:55 +02:00
|
|
|
assert_eq!(
|
|
|
|
"hello",
|
2020-07-03 16:42:56 +02:00
|
|
|
from_dynamic::<String>(&"hello".to_string().into())?
|
2020-07-03 11:19:55 +02:00
|
|
|
);
|
2020-07-03 16:42:56 +02:00
|
|
|
|
|
|
|
Ok(())
|
2020-07-03 11:19:55 +02:00
|
|
|
}
|
|
|
|
|
2020-07-05 05:35:50 +02:00
|
|
|
#[test]
|
|
|
|
fn test_serde_de_integer_types() -> Result<(), Box<EvalAltResult>> {
|
2021-01-18 03:30:58 +01:00
|
|
|
assert_eq!(42, from_dynamic::<i8>(&Dynamic::from(42 as INT))?);
|
|
|
|
assert_eq!(42, from_dynamic::<i16>(&Dynamic::from(42 as INT))?);
|
|
|
|
assert_eq!(42, from_dynamic::<i32>(&Dynamic::from(42 as INT))?);
|
|
|
|
assert_eq!(42, from_dynamic::<i64>(&Dynamic::from(42 as INT))?);
|
|
|
|
assert_eq!(42, from_dynamic::<u8>(&Dynamic::from(42 as INT))?);
|
|
|
|
assert_eq!(42, from_dynamic::<u16>(&Dynamic::from(42 as INT))?);
|
|
|
|
assert_eq!(42, from_dynamic::<u32>(&Dynamic::from(42 as INT))?);
|
|
|
|
assert_eq!(42, from_dynamic::<u64>(&Dynamic::from(42 as INT))?);
|
2020-07-05 05:35:50 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-07-03 11:19:55 +02:00
|
|
|
#[test]
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
2020-07-03 16:42:56 +02:00
|
|
|
fn test_serde_de_array() -> Result<(), Box<EvalAltResult>> {
|
2020-07-03 11:19:55 +02:00
|
|
|
let arr: Vec<INT> = vec![123, 456, 42, 999];
|
2020-07-03 16:42:56 +02:00
|
|
|
assert_eq!(arr, from_dynamic::<Vec<INT>>(&arr.clone().into())?);
|
|
|
|
Ok(())
|
2020-07-03 11:19:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-07-03 16:42:56 +02:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
fn test_serde_de_struct() -> Result<(), Box<EvalAltResult>> {
|
2020-07-03 11:19:55 +02:00
|
|
|
#[derive(Debug, Deserialize, PartialEq)]
|
|
|
|
struct Hello {
|
|
|
|
a: INT,
|
|
|
|
b: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize, PartialEq)]
|
|
|
|
struct Test {
|
|
|
|
int: u32,
|
|
|
|
seq: Vec<String>,
|
|
|
|
obj: Hello,
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut map = Map::new();
|
|
|
|
map.insert("int".into(), Dynamic::from(42_u32));
|
|
|
|
|
|
|
|
let mut map2 = Map::new();
|
|
|
|
map2.insert("a".into(), (123 as INT).into());
|
|
|
|
map2.insert("b".into(), true.into());
|
|
|
|
|
|
|
|
map.insert("obj".into(), map2.into());
|
|
|
|
|
|
|
|
let arr: Array = vec!["hello".into(), "kitty".into(), "world".into()];
|
|
|
|
map.insert("seq".into(), arr.into());
|
|
|
|
|
|
|
|
let expected = Test {
|
|
|
|
int: 42,
|
|
|
|
seq: vec!["hello".into(), "kitty".into(), "world".into()],
|
|
|
|
obj: Hello { a: 123, b: true },
|
|
|
|
};
|
2020-07-03 16:42:56 +02:00
|
|
|
assert_eq!(expected, from_dynamic(&map.into())?);
|
|
|
|
|
|
|
|
Ok(())
|
2020-07-03 11:19:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-07-03 16:42:56 +02:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2020-07-03 11:19:55 +02:00
|
|
|
fn test_serde_de_script() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
struct Point {
|
2021-04-06 17:18:28 +02:00
|
|
|
x: FLOAT,
|
|
|
|
y: FLOAT,
|
2020-07-03 11:19:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
struct MyStruct {
|
|
|
|
a: i64,
|
|
|
|
b: Vec<String>,
|
|
|
|
c: bool,
|
|
|
|
d: Point,
|
|
|
|
}
|
|
|
|
|
|
|
|
let engine = Engine::new();
|
|
|
|
|
|
|
|
let result: Dynamic = engine.eval(
|
|
|
|
r#"
|
|
|
|
#{
|
|
|
|
a: 42,
|
|
|
|
b: [ "hello", "world" ],
|
|
|
|
c: true,
|
|
|
|
d: #{ x: 123.456, y: 999.0 }
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)?;
|
|
|
|
|
|
|
|
// Convert the 'Dynamic' object map into 'MyStruct'
|
2020-07-03 16:42:56 +02:00
|
|
|
let _: MyStruct = from_dynamic(&result)?;
|
2020-07-03 11:19:55 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-07-05 05:43:48 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_serde_de_unit_enum() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
#[derive(Debug, PartialEq, Deserialize)]
|
|
|
|
enum MyEnum {
|
|
|
|
VariantFoo,
|
|
|
|
VariantBar,
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let d = Dynamic::from("VariantFoo".to_string());
|
|
|
|
assert_eq!(MyEnum::VariantFoo, from_dynamic(&d)?);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let d = Dynamic::from("VariantBar".to_string());
|
|
|
|
assert_eq!(MyEnum::VariantBar, from_dynamic(&d)?);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
fn test_serde_de_externally_tagged_enum() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
#[derive(Debug, PartialEq, Deserialize)]
|
|
|
|
#[serde(deny_unknown_fields)]
|
|
|
|
enum MyEnum {
|
|
|
|
VariantUnit,
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
VariantUnitTuple(),
|
|
|
|
VariantNewtype(i32),
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
VariantTuple(i32, i32),
|
|
|
|
VariantEmptyStruct {},
|
|
|
|
VariantStruct {
|
|
|
|
a: i32,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let d = Dynamic::from("VariantUnit".to_string());
|
|
|
|
assert_eq!(MyEnum::VariantUnit, from_dynamic(&d).unwrap());
|
2020-07-05 05:43:48 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
{
|
|
|
|
let array: Array = vec![];
|
|
|
|
let mut map_outer = Map::new();
|
|
|
|
map_outer.insert("VariantUnitTuple".into(), array.into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantUnitTuple(),
|
|
|
|
from_dynamic(&map_outer.into()).unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map_outer = Map::new();
|
|
|
|
map_outer.insert("VariantNewtype".into(), (123 as INT).into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantNewtype(123),
|
|
|
|
from_dynamic(&map_outer.into()).unwrap()
|
|
|
|
);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
{
|
|
|
|
let array: Array = vec![(123 as INT).into(), (456 as INT).into()];
|
|
|
|
let mut map_outer = Map::new();
|
|
|
|
map_outer.insert("VariantTuple".into(), array.into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantTuple(123, 456),
|
|
|
|
from_dynamic(&map_outer.into()).unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let map_inner = Map::new();
|
|
|
|
let mut map_outer = Map::new();
|
|
|
|
map_outer.insert("VariantEmptyStruct".into(), map_inner.into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantEmptyStruct {},
|
|
|
|
from_dynamic(&map_outer.into()).unwrap()
|
|
|
|
);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map_inner = Map::new();
|
|
|
|
map_inner.insert("a".into(), (123 as INT).into());
|
|
|
|
let mut map_outer = Map::new();
|
|
|
|
map_outer.insert("VariantStruct".into(), map_inner.into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantStruct { a: 123 },
|
|
|
|
from_dynamic(&map_outer.into()).unwrap()
|
|
|
|
);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
fn test_serde_de_internally_tagged_enum() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
#[derive(Debug, PartialEq, Deserialize)]
|
|
|
|
#[serde(tag = "tag", deny_unknown_fields)]
|
|
|
|
enum MyEnum {
|
|
|
|
VariantEmptyStruct {},
|
|
|
|
VariantStruct { a: i32 },
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map = Map::new();
|
|
|
|
map.insert("tag".into(), "VariantStruct".into());
|
|
|
|
map.insert("a".into(), (123 as INT).into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantStruct { a: 123 },
|
|
|
|
from_dynamic(&map.into()).unwrap()
|
|
|
|
);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map = Map::new();
|
|
|
|
map.insert("tag".into(), "VariantEmptyStruct".into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantEmptyStruct {},
|
|
|
|
from_dynamic(&map.into()).unwrap()
|
|
|
|
);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
fn test_serde_de_adjacently_tagged_enum() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
#[derive(Debug, PartialEq, Deserialize)]
|
|
|
|
#[serde(tag = "tag", content = "content", deny_unknown_fields)]
|
|
|
|
enum MyEnum {
|
|
|
|
VariantUnit,
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
VariantUnitTuple(),
|
|
|
|
VariantNewtype(i32),
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
VariantTuple(i32, i32),
|
|
|
|
VariantEmptyStruct {},
|
|
|
|
VariantStruct {
|
|
|
|
a: i32,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map_outer = Map::new();
|
|
|
|
map_outer.insert("tag".into(), "VariantUnit".into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantUnit,
|
|
|
|
from_dynamic(&map_outer.into()).unwrap()
|
|
|
|
);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
{
|
|
|
|
let array: Array = vec![];
|
|
|
|
let mut map_outer = Map::new();
|
|
|
|
map_outer.insert("tag".into(), "VariantUnitTuple".into());
|
|
|
|
map_outer.insert("content".into(), array.into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantUnitTuple(),
|
|
|
|
from_dynamic(&map_outer.into()).unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map_outer = Map::new();
|
|
|
|
map_outer.insert("tag".into(), "VariantNewtype".into());
|
|
|
|
map_outer.insert("content".into(), (123 as INT).into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantNewtype(123),
|
|
|
|
from_dynamic(&map_outer.into()).unwrap()
|
|
|
|
);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
{
|
|
|
|
let array: Array = vec![(123 as INT).into(), (456 as INT).into()];
|
|
|
|
let mut map_outer = Map::new();
|
|
|
|
map_outer.insert("tag".into(), "VariantTuple".into());
|
|
|
|
map_outer.insert("content".into(), array.into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantTuple(123, 456),
|
|
|
|
from_dynamic(&map_outer.into()).unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let map_inner = Map::new();
|
|
|
|
let mut map_outer = Map::new();
|
|
|
|
map_outer.insert("tag".into(), "VariantEmptyStruct".into());
|
|
|
|
map_outer.insert("content".into(), map_inner.into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantEmptyStruct {},
|
|
|
|
from_dynamic(&map_outer.into()).unwrap()
|
|
|
|
);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map_inner = Map::new();
|
|
|
|
map_inner.insert("a".into(), (123 as INT).into());
|
|
|
|
let mut map_outer = Map::new();
|
|
|
|
map_outer.insert("tag".into(), "VariantStruct".into());
|
|
|
|
map_outer.insert("content".into(), map_inner.into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantStruct { a: 123 },
|
|
|
|
from_dynamic(&map_outer.into()).unwrap()
|
|
|
|
);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
fn test_serde_de_untagged_enum() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
#[derive(Debug, PartialEq, Deserialize)]
|
|
|
|
#[serde(untagged, deny_unknown_fields)]
|
|
|
|
enum MyEnum {
|
|
|
|
VariantEmptyStruct {},
|
|
|
|
VariantStruct1 { a: i32 },
|
|
|
|
VariantStruct2 { b: i32 },
|
|
|
|
}
|
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let map = Map::new();
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantEmptyStruct {},
|
|
|
|
from_dynamic(&map.into()).unwrap()
|
|
|
|
);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map = Map::new();
|
|
|
|
map.insert("a".into(), (123 as INT).into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantStruct1 { a: 123 },
|
|
|
|
from_dynamic(&map.into()).unwrap()
|
|
|
|
);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
2020-10-10 08:15:23 +02:00
|
|
|
let mut map = Map::new();
|
|
|
|
map.insert("b".into(), (123 as INT).into());
|
|
|
|
assert_eq!(
|
|
|
|
MyEnum::VariantStruct2 { b: 123 },
|
|
|
|
from_dynamic(&map.into()).unwrap()
|
|
|
|
);
|
2020-07-05 05:43:48 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2021-01-18 03:30:58 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(feature = "metadata")]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
fn test_serde_json() -> serde_json::Result<()> {
|
|
|
|
let s: ImmutableString = "hello".into();
|
|
|
|
assert_eq!(serde_json::to_string(&s)?, r#""hello""#);
|
|
|
|
|
|
|
|
let mut map = Map::new();
|
|
|
|
map.insert("a".into(), (123 as INT).into());
|
|
|
|
|
|
|
|
let arr: Array = vec![(1 as INT).into(), (2 as INT).into(), (3 as INT).into()];
|
|
|
|
map.insert("b".into(), arr.into());
|
|
|
|
map.insert("c".into(), true.into());
|
|
|
|
let d: Dynamic = map.into();
|
|
|
|
|
|
|
|
let json = serde_json::to_string(&d)?;
|
|
|
|
|
|
|
|
assert!(json.contains("\"a\":123"));
|
|
|
|
assert!(json.contains("\"b\":[1,2,3]"));
|
|
|
|
assert!(json.contains("\"c\":true"));
|
|
|
|
|
|
|
|
let d2: Dynamic = serde_json::from_str(&json)?;
|
|
|
|
|
|
|
|
assert!(d2.is::<Map>());
|
|
|
|
|
|
|
|
let mut m = d2.cast::<Map>();
|
|
|
|
|
|
|
|
assert_eq!(m["a"].as_int().unwrap(), 123);
|
|
|
|
assert!(m["c"].as_bool().unwrap());
|
|
|
|
|
|
|
|
let a = m.remove("b").unwrap().cast::<Array>();
|
|
|
|
|
|
|
|
assert_eq!(a.len(), 3);
|
|
|
|
assert_eq!(format!("{:?}", a), "[1, 2, 3]");
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2021-12-02 05:50:11 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
fn test_serde_optional() -> Result<(), Box<EvalAltResult>> {
|
2022-01-13 12:02:37 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
2021-12-02 05:50:11 +01:00
|
|
|
struct TestStruct {
|
|
|
|
foo: Option<char>,
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
engine.register_type_with_name::<TestStruct>("TestStruct");
|
|
|
|
|
|
|
|
let r = engine.eval::<Dynamic>("#{ foo: 'a' }")?;
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
from_dynamic::<TestStruct>(&r)?,
|
|
|
|
TestStruct { foo: Some('a') }
|
|
|
|
);
|
|
|
|
|
|
|
|
let r = engine.eval::<Dynamic>("#{ foo: () }")?;
|
|
|
|
|
|
|
|
assert_eq!(from_dynamic::<TestStruct>(&r)?, TestStruct { foo: None });
|
|
|
|
|
|
|
|
let r = engine.eval::<Dynamic>("#{ }")?;
|
|
|
|
|
|
|
|
assert_eq!(from_dynamic::<TestStruct>(&r)?, TestStruct { foo: None });
|
|
|
|
|
2022-01-13 12:02:37 +01:00
|
|
|
let ts = TestStruct { foo: Some('a') };
|
|
|
|
|
|
|
|
let r = to_dynamic(&ts)?;
|
|
|
|
|
|
|
|
let map = r.cast::<Map>();
|
|
|
|
|
|
|
|
assert_eq!(map.len(), 1);
|
|
|
|
assert_eq!(map.get("foo").unwrap().as_char().unwrap(), 'a');
|
|
|
|
|
|
|
|
let ts = TestStruct { foo: None };
|
|
|
|
|
|
|
|
let r = to_dynamic(&ts)?;
|
|
|
|
|
|
|
|
let map = r.cast::<Map>();
|
|
|
|
|
|
|
|
assert_eq!(map.len(), 1);
|
|
|
|
assert_eq!(map.get("foo").unwrap().as_unit().unwrap(), ());
|
|
|
|
|
2021-12-02 05:50:11 +01:00
|
|
|
Ok(())
|
|
|
|
}
|
2021-12-02 07:10:53 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
fn test_serde_blob() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
let engine = Engine::new();
|
|
|
|
|
|
|
|
let r = engine.eval::<Dynamic>(
|
|
|
|
"
|
|
|
|
let x = blob(10);
|
2021-12-15 05:06:17 +01:00
|
|
|
for i in 0..10 { x[i] = i; }
|
2021-12-02 07:10:53 +01:00
|
|
|
x
|
|
|
|
",
|
|
|
|
)?;
|
|
|
|
|
|
|
|
let r = from_dynamic::<serde_bytes::ByteBuf>(&r)?;
|
|
|
|
|
|
|
|
assert_eq!(r.to_vec(), vec![0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2022-05-23 16:40:49 +02:00
|
|
|
|
|
|
|
#[test]
|
2022-05-23 16:58:15 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2022-05-23 16:40:49 +02:00
|
|
|
fn test_serde_json_borrowed_string() {
|
|
|
|
let value = json!({ "a": "b" });
|
|
|
|
println!("value: {:?}", value);
|
|
|
|
let _: Dynamic = serde_json::from_value(value).unwrap();
|
|
|
|
}
|