Merge pull request #16 from alvinhochun/serde

Handle deserialization of all integer and impl. serde for all enum types
This commit is contained in:
Stephen Chung 2020-07-06 21:30:42 +08:00 committed by GitHub
commit de934e6254
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 783 additions and 77 deletions

View File

@ -7,7 +7,10 @@ use crate::result::EvalAltResult;
use crate::token::Position; use crate::token::Position;
use crate::utils::ImmutableString; use crate::utils::ImmutableString;
use serde::de::{DeserializeSeed, Deserializer, Error, MapAccess, SeqAccess, Visitor}; use serde::de::{
DeserializeSeed, Deserializer, EnumAccess, Error, IntoDeserializer, MapAccess, SeqAccess,
VariantAccess, Visitor,
};
use serde::Deserialize; use serde::Deserialize;
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
@ -49,6 +52,20 @@ impl<'de> DynamicDeserializer<'de> {
Position::none(), Position::none(),
))) )))
} }
fn deserialize_int<V: Visitor<'de>>(
&mut self,
v: crate::INT,
visitor: V,
) -> Result<V::Value, Box<EvalAltResult>> {
#[cfg(not(feature = "only_i32"))]
{
visitor.visit_i64(v)
}
#[cfg(feature = "only_i32")]
{
visitor.visit_i32(v)
}
}
} }
/// Deserialize a `Dynamic` value into a Rust type that implements `serde::Deserialize`. /// Deserialize a `Dynamic` value into a Rust type that implements `serde::Deserialize`.
@ -159,51 +176,87 @@ impl<'de> Deserializer<'de> for &mut DynamicDeserializer<'de> {
} }
fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> { fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> {
self.value if let Ok(v) = self.value.as_int() {
.downcast_ref::<i8>() self.deserialize_int(v, visitor)
.map_or_else(|| self.type_error(), |&x| visitor.visit_i8(x)) } else {
self.value
.downcast_ref::<i8>()
.map_or_else(|| self.type_error(), |&x| visitor.visit_i8(x))
}
} }
fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> { fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> {
self.value if let Ok(v) = self.value.as_int() {
.downcast_ref::<i16>() self.deserialize_int(v, visitor)
.map_or_else(|| self.type_error(), |&x| visitor.visit_i16(x)) } else {
self.value
.downcast_ref::<i16>()
.map_or_else(|| self.type_error(), |&x| visitor.visit_i16(x))
}
} }
fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> { fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> {
self.value if let Ok(v) = self.value.as_int() {
.downcast_ref::<i32>() self.deserialize_int(v, visitor)
.map_or_else(|| self.type_error(), |&x| visitor.visit_i32(x)) } else if cfg!(feature = "only_i32") {
self.type_error()
} else {
self.value
.downcast_ref::<i32>()
.map_or_else(|| self.type_error(), |&x| visitor.visit_i32(x))
}
} }
fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> { fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> {
self.value if let Ok(v) = self.value.as_int() {
.downcast_ref::<i64>() self.deserialize_int(v, visitor)
.map_or_else(|| self.type_error(), |&x| visitor.visit_i64(x)) } else if cfg!(not(feature = "only_i32")) {
self.type_error()
} else {
self.value
.downcast_ref::<i64>()
.map_or_else(|| self.type_error(), |&x| visitor.visit_i64(x))
}
} }
fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> { fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> {
self.value if let Ok(v) = self.value.as_int() {
.downcast_ref::<u8>() self.deserialize_int(v, visitor)
.map_or_else(|| self.type_error(), |&x| visitor.visit_u8(x)) } else {
self.value
.downcast_ref::<u8>()
.map_or_else(|| self.type_error(), |&x| visitor.visit_u8(x))
}
} }
fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> { fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> {
self.value if let Ok(v) = self.value.as_int() {
.downcast_ref::<u16>() self.deserialize_int(v, visitor)
.map_or_else(|| self.type_error(), |&x| visitor.visit_u16(x)) } else {
self.value
.downcast_ref::<u16>()
.map_or_else(|| self.type_error(), |&x| visitor.visit_u16(x))
}
} }
fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> { fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> {
self.value if let Ok(v) = self.value.as_int() {
.downcast_ref::<u32>() self.deserialize_int(v, visitor)
.map_or_else(|| self.type_error(), |&x| visitor.visit_u32(x)) } else {
self.value
.downcast_ref::<u32>()
.map_or_else(|| self.type_error(), |&x| visitor.visit_u32(x))
}
} }
fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> { fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> {
self.value if let Ok(v) = self.value.as_int() {
.downcast_ref::<u64>() self.deserialize_int(v, visitor)
.map_or_else(|| self.type_error(), |&x| visitor.visit_u64(x)) } else {
self.value
.downcast_ref::<u64>()
.map_or_else(|| self.type_error(), |&x| visitor.visit_u64(x))
}
} }
fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> { fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Box<EvalAltResult>> {
@ -334,9 +387,30 @@ impl<'de> Deserializer<'de> for &mut DynamicDeserializer<'de> {
self, self,
_name: &'static str, _name: &'static str,
_variants: &'static [&'static str], _variants: &'static [&'static str],
_: V, visitor: V,
) -> Result<V::Value, Box<EvalAltResult>> { ) -> Result<V::Value, Box<EvalAltResult>> {
self.type_error() if let Ok(s) = self.value.as_str() {
visitor.visit_enum(s.into_deserializer())
} else {
#[cfg(not(feature = "no_object"))]
if let Some(map) = self.value.downcast_ref::<Map>() {
let mut iter = map.iter();
let first = iter.next();
let second = iter.next();
if let (Some((key, value)), None) = (first, second) {
visitor.visit_enum(EnumDeserializer {
tag: &key,
content: DynamicDeserializer::from_dynamic(value),
})
} else {
self.type_error()
}
} else {
self.type_error()
}
#[cfg(feature = "no_object")]
return self.type_error();
}
} }
fn deserialize_identifier<V: Visitor<'de>>( fn deserialize_identifier<V: Visitor<'de>>(
@ -444,3 +518,57 @@ where
)) ))
} }
} }
#[cfg(not(feature = "no_object"))]
struct EnumDeserializer<'t, 'de: 't> {
tag: &'t str,
content: DynamicDeserializer<'de>,
}
#[cfg(not(feature = "no_object"))]
impl<'t, 'de> EnumAccess<'de> for EnumDeserializer<'t, 'de> {
type Error = Box<EvalAltResult>;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: DeserializeSeed<'de>,
{
seed.deserialize(self.tag.into_deserializer())
.map(|v| (v, self))
}
}
#[cfg(not(feature = "no_object"))]
impl<'t, 'de> VariantAccess<'de> for EnumDeserializer<'t, 'de> {
type Error = Box<EvalAltResult>;
fn unit_variant(mut self) -> Result<(), Self::Error> {
Deserialize::deserialize(&mut self.content)
}
fn newtype_variant_seed<T>(mut self, seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>,
{
seed.deserialize(&mut self.content)
}
fn tuple_variant<V>(mut self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.content.deserialize_tuple(len, visitor)
}
fn struct_variant<V>(
mut self,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.content.deserialize_struct("", fields, visitor)
}
}

View File

@ -103,10 +103,16 @@ impl Serializer for &mut DynamicSerializer {
type SerializeSeq = DynamicSerializer; type SerializeSeq = DynamicSerializer;
type SerializeTuple = DynamicSerializer; type SerializeTuple = DynamicSerializer;
type SerializeTupleStruct = DynamicSerializer; type SerializeTupleStruct = DynamicSerializer;
type SerializeTupleVariant = DynamicSerializer; #[cfg(not(any(feature = "no_object", feature = "no_index")))]
type SerializeTupleVariant = TupleVariantSerializer;
#[cfg(any(feature = "no_object", feature = "no_index"))]
type SerializeTupleVariant = serde::ser::Impossible<Dynamic, Box<EvalAltResult>>;
type SerializeMap = DynamicSerializer; type SerializeMap = DynamicSerializer;
type SerializeStruct = DynamicSerializer; type SerializeStruct = DynamicSerializer;
type SerializeStructVariant = DynamicSerializer; #[cfg(not(feature = "no_object"))]
type SerializeStructVariant = StructVariantSerializer;
#[cfg(feature = "no_object")]
type SerializeStructVariant = serde::ser::Impossible<Dynamic, Box<EvalAltResult>>;
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Box<EvalAltResult>> { fn serialize_bool(self, v: bool) -> Result<Self::Ok, Box<EvalAltResult>> {
Ok(v.into()) Ok(v.into())
@ -162,7 +168,7 @@ impl Serializer for &mut DynamicSerializer {
#[cfg(not(feature = "only_i32"))] #[cfg(not(feature = "only_i32"))]
return self.serialize_i64(i64::from(v)); return self.serialize_i64(i64::from(v));
#[cfg(feature = "only_i32")] #[cfg(feature = "only_i32")]
if v > i32::MAX as u64 { if v > i32::MAX as u32 {
return Ok(Dynamic::from(v)); return Ok(Dynamic::from(v));
} else { } else {
return self.serialize_i32(v as i32); return self.serialize_i32(v as i32);
@ -244,10 +250,20 @@ impl Serializer for &mut DynamicSerializer {
self, self,
_name: &'static str, _name: &'static str,
_variant_index: u32, _variant_index: u32,
_variant: &'static str, variant: &'static str,
value: &T, value: &T,
) -> Result<Self::Ok, Box<EvalAltResult>> { ) -> Result<Self::Ok, Box<EvalAltResult>> {
value.serialize(&mut *self) #[cfg(not(feature = "no_object"))]
{
let content = to_dynamic(value)?;
make_variant(variant, content)
}
#[cfg(feature = "no_object")]
return Err(Box::new(EvalAltResult::ErrorMismatchOutputType(
"Dynamic".into(),
"map".into(),
Position::none(),
)));
} }
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Box<EvalAltResult>> { fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Box<EvalAltResult>> {
@ -277,10 +293,26 @@ impl Serializer for &mut DynamicSerializer {
self, self,
_name: &'static str, _name: &'static str,
_variant_index: u32, _variant_index: u32,
_variant: &'static str, variant: &'static str,
len: usize, len: usize,
) -> Result<Self::SerializeTupleVariant, Box<EvalAltResult>> { ) -> Result<Self::SerializeTupleVariant, Box<EvalAltResult>> {
self.serialize_seq(Some(len)) #[cfg(not(any(feature = "no_object", feature = "no_index")))]
return Ok(TupleVariantSerializer {
variant,
array: Array::with_capacity(len),
});
#[cfg(any(feature = "no_object", feature = "no_index"))]
{
#[cfg(feature = "no_object")]
let err_type = "map";
#[cfg(not(feature = "no_object"))]
let err_type = "array";
Err(Box::new(EvalAltResult::ErrorMismatchOutputType(
"Dynamic".into(),
err_type.into(),
Position::none(),
)))
}
} }
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Box<EvalAltResult>> { fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Box<EvalAltResult>> {
@ -306,10 +338,20 @@ impl Serializer for &mut DynamicSerializer {
self, self,
_name: &'static str, _name: &'static str,
_variant_index: u32, _variant_index: u32,
_variant: &'static str, variant: &'static str,
len: usize, len: usize,
) -> Result<Self::SerializeStructVariant, Box<EvalAltResult>> { ) -> Result<Self::SerializeStructVariant, Box<EvalAltResult>> {
self.serialize_map(Some(len)) #[cfg(not(feature = "no_object"))]
return Ok(StructVariantSerializer {
variant,
map: Map::with_capacity(len),
});
#[cfg(feature = "no_object")]
return Err(Box::new(EvalAltResult::ErrorMismatchOutputType(
"Dynamic".into(),
"map".into(),
Position::none(),
)));
} }
} }
@ -395,33 +437,6 @@ impl SerializeTupleStruct for DynamicSerializer {
} }
} }
impl SerializeTupleVariant for DynamicSerializer {
type Ok = Dynamic;
type Error = Box<EvalAltResult>;
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
value: &T,
) -> Result<(), Box<EvalAltResult>> {
#[cfg(not(feature = "no_index"))]
{
let value = value.serialize(&mut *self)?;
let arr = self.value.downcast_mut::<Array>().unwrap();
arr.push(value);
Ok(())
}
#[cfg(feature = "no_index")]
unreachable!()
}
fn end(self) -> Result<Self::Ok, Box<EvalAltResult>> {
#[cfg(not(feature = "no_index"))]
return Ok(self.value);
#[cfg(feature = "no_index")]
unreachable!()
}
}
impl SerializeMap for DynamicSerializer { impl SerializeMap for DynamicSerializer {
type Ok = Dynamic; type Ok = Dynamic;
type Error = Box<EvalAltResult>; type Error = Box<EvalAltResult>;
@ -520,7 +535,39 @@ impl SerializeStruct for DynamicSerializer {
} }
} }
impl SerializeStructVariant for DynamicSerializer { #[cfg(not(any(feature = "no_object", feature = "no_index")))]
pub struct TupleVariantSerializer {
variant: &'static str,
array: Array,
}
#[cfg(not(any(feature = "no_object", feature = "no_index")))]
impl SerializeTupleVariant for TupleVariantSerializer {
type Ok = Dynamic;
type Error = Box<EvalAltResult>;
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
value: &T,
) -> Result<(), Box<EvalAltResult>> {
let value = to_dynamic(value)?;
self.array.push(value);
Ok(())
}
fn end(self) -> Result<Self::Ok, Box<EvalAltResult>> {
make_variant(self.variant, self.array.into())
}
}
#[cfg(not(feature = "no_object"))]
pub struct StructVariantSerializer {
variant: &'static str,
map: Map,
}
#[cfg(not(feature = "no_object"))]
impl SerializeStructVariant for StructVariantSerializer {
type Ok = Dynamic; type Ok = Dynamic;
type Error = Box<EvalAltResult>; type Error = Box<EvalAltResult>;
@ -529,21 +576,19 @@ impl SerializeStructVariant for DynamicSerializer {
key: &'static str, key: &'static str,
value: &T, value: &T,
) -> Result<(), Box<EvalAltResult>> { ) -> Result<(), Box<EvalAltResult>> {
#[cfg(not(feature = "no_object"))] let value = to_dynamic(value)?;
{ self.map.insert(key.into(), value);
let value = value.serialize(&mut *self)?; Ok(())
let map = self.value.downcast_mut::<Map>().unwrap();
map.insert(key.into(), value);
Ok(())
}
#[cfg(feature = "no_object")]
unreachable!()
} }
fn end(self) -> Result<Self::Ok, Box<EvalAltResult>> { fn end(self) -> Result<Self::Ok, Box<EvalAltResult>> {
#[cfg(not(feature = "no_object"))] make_variant(self.variant, self.map.into())
return Ok(self.value);
#[cfg(feature = "no_object")]
unreachable!()
} }
} }
#[cfg(not(feature = "no_object"))]
fn make_variant(variant: &'static str, value: Dynamic) -> Result<Dynamic, Box<EvalAltResult>> {
let mut map = Map::with_capacity(1);
map.insert(variant.into(), value);
Ok(map.into())
}

View File

@ -33,6 +33,38 @@ fn test_serde_ser_primary_types() -> Result<(), Box<EvalAltResult>> {
Ok(()) Ok(())
} }
#[test]
fn test_serde_ser_integer_types() -> Result<(), Box<EvalAltResult>> {
assert_eq!(to_dynamic(42_i8)?.type_name(), std::any::type_name::<INT>());
assert_eq!(
to_dynamic(42_i16)?.type_name(),
std::any::type_name::<INT>()
);
assert_eq!(
to_dynamic(42_i32)?.type_name(),
std::any::type_name::<INT>()
);
assert_eq!(
to_dynamic(42_i64)?.type_name(),
std::any::type_name::<INT>()
);
assert_eq!(to_dynamic(42_u8)?.type_name(), std::any::type_name::<INT>());
assert_eq!(
to_dynamic(42_u16)?.type_name(),
std::any::type_name::<INT>()
);
assert_eq!(
to_dynamic(42_u32)?.type_name(),
std::any::type_name::<INT>()
);
assert_eq!(
to_dynamic(42_u64)?.type_name(),
std::any::type_name::<INT>()
);
Ok(())
}
#[test] #[test]
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
fn test_serde_ser_array() -> Result<(), Box<EvalAltResult>> { fn test_serde_ser_array() -> Result<(), Box<EvalAltResult>> {
@ -85,6 +117,235 @@ fn test_serde_ser_struct() -> Result<(), Box<EvalAltResult>> {
Ok(()) Ok(())
} }
#[test]
fn test_serde_ser_unit_enum() -> Result<(), Box<EvalAltResult>> {
#[derive(Serialize)]
enum MyEnum {
VariantFoo,
VariantBar,
}
let d = to_dynamic(MyEnum::VariantFoo)?;
assert_eq!("VariantFoo", d.as_str().unwrap());
let d = to_dynamic(MyEnum::VariantBar)?;
assert_eq!("VariantBar", d.as_str().unwrap());
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,
},
}
{
let d = to_dynamic(MyEnum::VariantUnit)?;
assert_eq!("VariantUnit", d.as_str().unwrap());
}
#[cfg(not(feature = "no_index"))]
{
let d = to_dynamic(MyEnum::VariantUnitTuple())?;
let mut map = d.cast::<Map>();
let content = map.remove("VariantUnitTuple").unwrap().cast::<Array>();
assert!(map.is_empty());
assert!(content.is_empty());
}
{
let d = to_dynamic(MyEnum::VariantNewtype(123))?;
let mut map = d.cast::<Map>();
let content = map.remove("VariantNewtype").unwrap();
assert!(map.is_empty());
assert_eq!(Ok(123), content.as_int());
}
#[cfg(not(feature = "no_index"))]
{
let d = to_dynamic(MyEnum::VariantTuple(123, 456))?;
let mut map = d.cast::<Map>();
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());
}
{
let d = to_dynamic(MyEnum::VariantEmptyStruct {})?;
let mut map = d.cast::<Map>();
let map_inner = map.remove("VariantEmptyStruct").unwrap().cast::<Map>();
assert!(map.is_empty());
assert!(map_inner.is_empty());
}
{
let d = to_dynamic(MyEnum::VariantStruct { a: 123 })?;
let mut map = d.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());
}
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 },
}
let d = to_dynamic(MyEnum::VariantEmptyStruct {})?;
let mut map = d.cast::<Map>();
assert_eq!(
Ok("VariantEmptyStruct"),
map.remove("tag").unwrap().as_str()
);
assert!(map.is_empty());
let d = to_dynamic(MyEnum::VariantStruct { a: 123 })?;
let mut map = d.cast::<Map>();
assert_eq!(Ok("VariantStruct"), map.remove("tag").unwrap().as_str());
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,
},
}
{
let d = to_dynamic(MyEnum::VariantUnit)?;
let mut map = d.cast::<Map>();
assert_eq!(Ok("VariantUnit"), map.remove("tag").unwrap().as_str());
assert!(map.is_empty());
}
#[cfg(not(feature = "no_index"))]
{
let d = to_dynamic(MyEnum::VariantUnitTuple())?;
let mut map = d.cast::<Map>();
assert_eq!(Ok("VariantUnitTuple"), map.remove("tag").unwrap().as_str());
let content = map.remove("content").unwrap().cast::<Array>();
assert!(map.is_empty());
assert!(content.is_empty());
}
{
let d = to_dynamic(MyEnum::VariantNewtype(123))?;
let mut map = d.cast::<Map>();
assert_eq!(Ok("VariantNewtype"), map.remove("tag").unwrap().as_str());
let content = map.remove("content").unwrap();
assert!(map.is_empty());
assert_eq!(Ok(123), content.as_int());
}
#[cfg(not(feature = "no_index"))]
{
let d = to_dynamic(MyEnum::VariantTuple(123, 456))?;
let mut map = d.cast::<Map>();
assert_eq!(Ok("VariantTuple"), map.remove("tag").unwrap().as_str());
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());
}
{
let d = to_dynamic(MyEnum::VariantEmptyStruct {})?;
let mut map = d.cast::<Map>();
assert_eq!(
Ok("VariantEmptyStruct"),
map.remove("tag").unwrap().as_str()
);
let map_inner = map.remove("content").unwrap().cast::<Map>();
assert!(map.is_empty());
assert!(map_inner.is_empty());
}
{
let d = to_dynamic(MyEnum::VariantStruct { a: 123 })?;
let mut map = d.cast::<Map>();
assert_eq!(Ok("VariantStruct"), map.remove("tag").unwrap().as_str());
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());
}
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 },
}
{
let d = to_dynamic(MyEnum::VariantEmptyStruct {})?;
let map = d.cast::<Map>();
assert!(map.is_empty());
}
{
let d = to_dynamic(MyEnum::VariantStruct1 { a: 123 })?;
let mut map = d.cast::<Map>();
assert_eq!(Ok(123), map.remove("a").unwrap().as_int());
assert!(map.is_empty());
}
{
let d = to_dynamic(MyEnum::VariantStruct2 { b: 123 })?;
let mut map = d.cast::<Map>();
assert_eq!(Ok(123), map.remove("b").unwrap().as_int());
assert!(map.is_empty());
}
Ok(())
}
#[test] #[test]
fn test_serde_de_primary_types() -> Result<(), Box<EvalAltResult>> { fn test_serde_de_primary_types() -> Result<(), Box<EvalAltResult>> {
assert_eq!(42_u16, from_dynamic(&Dynamic::from(42_u16))?); assert_eq!(42_u16, from_dynamic(&Dynamic::from(42_u16))?);
@ -106,6 +367,20 @@ fn test_serde_de_primary_types() -> Result<(), Box<EvalAltResult>> {
Ok(()) Ok(())
} }
#[test]
fn test_serde_de_integer_types() -> Result<(), Box<EvalAltResult>> {
assert_eq!(42_i8, from_dynamic(&Dynamic::from(42 as INT))?);
assert_eq!(42_i16, from_dynamic(&Dynamic::from(42 as INT))?);
assert_eq!(42_i32, from_dynamic(&Dynamic::from(42 as INT))?);
assert_eq!(42_i64, from_dynamic(&Dynamic::from(42 as INT))?);
assert_eq!(42_u8, from_dynamic(&Dynamic::from(42 as INT))?);
assert_eq!(42_u16, from_dynamic(&Dynamic::from(42 as INT))?);
assert_eq!(42_u32, from_dynamic(&Dynamic::from(42 as INT))?);
assert_eq!(42_u64, from_dynamic(&Dynamic::from(42 as INT))?);
Ok(())
}
#[test] #[test]
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
fn test_serde_de_array() -> Result<(), Box<EvalAltResult>> { fn test_serde_de_array() -> Result<(), Box<EvalAltResult>> {
@ -190,3 +465,261 @@ fn test_serde_de_script() -> Result<(), Box<EvalAltResult>> {
Ok(()) Ok(())
} }
#[test]
fn test_serde_de_unit_enum() -> Result<(), Box<EvalAltResult>> {
#[derive(Debug, PartialEq, Deserialize)]
enum MyEnum {
VariantFoo,
VariantBar,
}
{
let d = Dynamic::from("VariantFoo".to_string());
assert_eq!(MyEnum::VariantFoo, from_dynamic(&d)?);
}
{
let d = Dynamic::from("VariantBar".to_string());
assert_eq!(MyEnum::VariantBar, from_dynamic(&d)?);
}
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,
},
}
{
let d = Dynamic::from("VariantUnit".to_string());
assert_eq!(MyEnum::VariantUnit, from_dynamic(&d).unwrap());
}
#[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()
);
}
{
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()
);
}
#[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()
);
}
{
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()
);
}
{
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()
);
}
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 },
}
{
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()
);
}
{
let mut map = Map::new();
map.insert("tag".into(), "VariantEmptyStruct".into());
assert_eq!(
MyEnum::VariantEmptyStruct {},
from_dynamic(&map.into()).unwrap()
);
}
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,
},
}
{
let mut map_outer = Map::new();
map_outer.insert("tag".into(), "VariantUnit".into());
assert_eq!(
MyEnum::VariantUnit,
from_dynamic(&map_outer.into()).unwrap()
);
}
#[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()
);
}
{
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()
);
}
#[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()
);
}
{
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()
);
}
{
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()
);
}
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 },
}
{
let map = Map::new();
assert_eq!(
MyEnum::VariantEmptyStruct {},
from_dynamic(&map.into()).unwrap()
);
}
{
let mut map = Map::new();
map.insert("a".into(), (123 as INT).into());
assert_eq!(
MyEnum::VariantStruct1 { a: 123 },
from_dynamic(&map.into()).unwrap()
);
}
{
let mut map = Map::new();
map.insert("b".into(), (123 as INT).into());
assert_eq!(
MyEnum::VariantStruct2 { b: 123 },
from_dynamic(&map.into()).unwrap()
);
}
Ok(())
}