|
1 | 1 | mod de; |
| 2 | +mod deserialize_reflect; |
2 | 3 | mod ser; |
3 | 4 | mod type_data; |
4 | 5 |
|
5 | 6 | pub use de::*; |
| 7 | +pub use deserialize_reflect::*; |
6 | 8 | pub use ser::*; |
7 | 9 | pub use type_data::*; |
8 | 10 |
|
9 | 11 | #[cfg(test)] |
10 | 12 | mod tests { |
11 | | - use crate::{self as bevy_reflect, DynamicTupleStruct}; |
| 13 | + use crate::{self as bevy_reflect, DynamicTupleStruct, ReflectDeserialize, Struct}; |
12 | 14 | use crate::{ |
13 | | - serde::{ReflectSerializer, UntypedReflectDeserializer}, |
| 15 | + serde::{ |
| 16 | + DeserializeReflect, ReflectDeserializeReflect, ReflectSerializer, |
| 17 | + TypedReflectDeserializer, UntypedReflectDeserializer, |
| 18 | + }, |
14 | 19 | type_registry::TypeRegistry, |
15 | 20 | DynamicStruct, Reflect, |
16 | 21 | }; |
17 | | - use serde::de::DeserializeSeed; |
| 22 | + use bevy_reflect_derive::FromReflect; |
| 23 | + use serde::de::{DeserializeSeed, SeqAccess, Visitor}; |
| 24 | + use serde::{Deserialize, Deserializer}; |
| 25 | + use std::fmt::Formatter; |
18 | 26 |
|
19 | 27 | #[test] |
20 | 28 | fn test_serialization_struct() { |
@@ -104,4 +112,138 @@ mod tests { |
104 | 112 | let serializer = ReflectSerializer::new(&value, ®istry); |
105 | 113 | ron::ser::to_string(&serializer).unwrap(); |
106 | 114 | } |
| 115 | + |
| 116 | + #[test] |
| 117 | + fn should_deserialize_using_deserialize_reflect() { |
| 118 | + #[derive(Reflect, FromReflect, PartialEq, Debug, Deserialize)] |
| 119 | + #[reflect(Deserialize)] |
| 120 | + enum AnimalType { |
| 121 | + Dog, |
| 122 | + Cat, |
| 123 | + } |
| 124 | + |
| 125 | + #[derive(Reflect, FromReflect)] |
| 126 | + struct Dog { |
| 127 | + name: DogName, |
| 128 | + } |
| 129 | + |
| 130 | + #[derive(Reflect, FromReflect)] |
| 131 | + enum DogName { |
| 132 | + Spot, |
| 133 | + Fido, |
| 134 | + Rex, |
| 135 | + } |
| 136 | + |
| 137 | + #[derive(Reflect, FromReflect)] |
| 138 | + struct Cat { |
| 139 | + name: CatName, |
| 140 | + } |
| 141 | + |
| 142 | + #[derive(Reflect, FromReflect)] |
| 143 | + enum CatName { |
| 144 | + Fluffy, |
| 145 | + Snowball, |
| 146 | + Luna, |
| 147 | + } |
| 148 | + |
| 149 | + /// Pet is made up of two fields: the type of animal and the animal itself. |
| 150 | + /// |
| 151 | + /// This allows us to store a type-erased version of our pet, |
| 152 | + /// rather than having to define one like this: |
| 153 | + /// |
| 154 | + /// ``` |
| 155 | + /// # use bevy_reflect::prelude::Reflect; |
| 156 | + /// #[derive(Reflect)] |
| 157 | + /// struct Pet<T: Reflect>(T); |
| 158 | + /// ``` |
| 159 | + /// |
| 160 | + /// If we wanted to allow for deserialization of any type, |
| 161 | + /// we could replace `AnimalType` with a `String` containing the type name of the animal. |
| 162 | + #[derive(Reflect)] |
| 163 | + #[reflect(DeserializeReflect)] |
| 164 | + struct Pet(AnimalType, DynamicStruct); |
| 165 | + |
| 166 | + impl<'de> DeserializeReflect<'de> for Pet { |
| 167 | + fn deserialize<D>(deserializer: D, registry: &TypeRegistry) -> Result<Self, D::Error> |
| 168 | + where |
| 169 | + D: Deserializer<'de>, |
| 170 | + { |
| 171 | + struct PetVisitor<'a> { |
| 172 | + registry: &'a TypeRegistry, |
| 173 | + } |
| 174 | + impl<'a, 'de> Visitor<'de> for PetVisitor<'a> { |
| 175 | + type Value = Pet; |
| 176 | + |
| 177 | + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { |
| 178 | + write!(formatter, "a pet tuple struct") |
| 179 | + } |
| 180 | + |
| 181 | + fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> |
| 182 | + where |
| 183 | + A: SeqAccess<'de>, |
| 184 | + { |
| 185 | + let kind = seq.next_element::<AnimalType>()?.unwrap(); |
| 186 | + match kind { |
| 187 | + AnimalType::Cat => { |
| 188 | + let cat = seq |
| 189 | + .next_element_seed(TypedReflectDeserializer::of::<Cat>( |
| 190 | + self.registry, |
| 191 | + ))? |
| 192 | + .unwrap() |
| 193 | + .take::<DynamicStruct>() |
| 194 | + .unwrap(); |
| 195 | + Ok(Pet(kind, cat)) |
| 196 | + } |
| 197 | + AnimalType::Dog => { |
| 198 | + let dog = seq |
| 199 | + .next_element_seed(TypedReflectDeserializer::of::<Dog>( |
| 200 | + self.registry, |
| 201 | + ))? |
| 202 | + .unwrap() |
| 203 | + .take::<DynamicStruct>() |
| 204 | + .unwrap(); |
| 205 | + Ok(Pet(kind, dog)) |
| 206 | + } |
| 207 | + } |
| 208 | + } |
| 209 | + } |
| 210 | + |
| 211 | + deserializer.deserialize_tuple_struct("Pet", 1, PetVisitor { registry }) |
| 212 | + } |
| 213 | + } |
| 214 | + |
| 215 | + let mut registry = TypeRegistry::default(); |
| 216 | + registry.register::<Pet>(); |
| 217 | + registry.register::<AnimalType>(); |
| 218 | + registry.register::<Dog>(); |
| 219 | + registry.register::<DogName>(); |
| 220 | + registry.register::<Cat>(); |
| 221 | + registry.register::<CatName>(); |
| 222 | + |
| 223 | + let pet = Pet( |
| 224 | + AnimalType::Cat, |
| 225 | + Cat { |
| 226 | + name: CatName::Fluffy, |
| 227 | + } |
| 228 | + .clone_dynamic(), |
| 229 | + ); |
| 230 | + |
| 231 | + let serializer = ReflectSerializer::new(&pet, ®istry); |
| 232 | + let serialized = ron::ser::to_string(&serializer).unwrap(); |
| 233 | + |
| 234 | + let expected = r#"{"bevy_reflect::serde::tests::should_deserialize_using_deserialize_reflect::Pet":(Cat,(name:Fluffy))}"#; |
| 235 | + |
| 236 | + assert_eq!(expected, serialized); |
| 237 | + |
| 238 | + let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap(); |
| 239 | + let reflect_deserializer = UntypedReflectDeserializer::new(®istry); |
| 240 | + let value = reflect_deserializer.deserialize(&mut deserializer).unwrap(); |
| 241 | + let deserialized = value.take::<Pet>().unwrap(); |
| 242 | + |
| 243 | + assert_eq!(pet.0, deserialized.0); |
| 244 | + assert!(pet |
| 245 | + .1 |
| 246 | + .reflect_partial_eq(&deserialized.1) |
| 247 | + .unwrap_or_default()); |
| 248 | + } |
107 | 249 | } |
0 commit comments