use bevy_reflect::{
PartialReflect, ReflectFromReflect, TypeRegistry,
serde::{ReflectDeserializer, ReflectSerializer},
};
use bincode::{de::read::SliceReader, error::EncodeError, serde::OwnedSerdeDecoder};
use serde::de::DeserializeSeed;
pub(crate) const BINCODE_OPTIONS: bincode::config::Configuration<
bincode::config::BigEndian,
bincode::config::Fixint,
> = bincode::config::standard()
.with_big_endian()
.with_fixed_int_encoding();
pub(crate) fn reflect_to_bin(
compo: &dyn PartialReflect,
registry: &TypeRegistry,
) -> Result<Vec<u8>, EncodeError> {
let serializer = ReflectSerializer::new(compo, registry);
bincode::serde::encode_to_vec(&serializer, BINCODE_OPTIONS)
}
pub(crate) fn bin_to_reflect(data: &[u8], registry: &TypeRegistry) -> Box<dyn PartialReflect> {
let reflect_deserializer = ReflectDeserializer::new(registry);
let mut bin_deser = OwnedSerdeDecoder::from_reader(SliceReader::new(data), BINCODE_OPTIONS);
let data = reflect_deserializer
.deserialize(bin_deser.as_deserializer())
.unwrap();
let type_path = data.get_represented_type_info().unwrap().type_path();
let registration = registry.get_with_type_path(type_path).unwrap();
let rfr = registry
.get_type_data::<ReflectFromReflect>(registration.type_id())
.unwrap();
rfr.from_reflect(&*data).unwrap().into_partial_reflect()
}
#[cfg(test)]
mod test {
use super::*;
use bevy_asset::Handle;
use bevy_color::Color;
use bevy_ecs::component::Component;
use bevy_image::Image;
use bevy_math::{Quat, Vec3};
use bevy_pbr::ParallaxMappingMethod;
use bevy_pbr::{OpaqueRendererMethod, StandardMaterial};
use bevy_reflect::{GetTypeRegistration, Reflect, ReflectFromReflect, TypeRegistry};
use bevy_render::alpha::AlphaMode;
use bevy_transform::components::Transform;
use serde::{Deserialize, Serialize};
#[derive(Component, Default, PartialEq, Serialize, Deserialize, Debug, Reflect)]
struct MyCompo {
value: i32,
name: String,
}
fn check_serialize_and_back<T>(compo_orig: &T)
where
T: Reflect + GetTypeRegistration + PartialEq + std::fmt::Debug,
{
let mut registry = TypeRegistry::default();
registry.register::<T>();
let data = reflect_to_bin(compo_orig.as_partial_reflect(), ®istry).unwrap();
let compo_result = bin_to_reflect(&data, ®istry);
let compo_result = compo_result.try_downcast::<T>().unwrap();
assert_eq!(*compo_result, *compo_orig);
}
#[test]
fn compo_data_serde() {
check_serialize_and_back::<MyCompo>(&MyCompo {
value: 3,
name: String::from("name"),
});
}
#[test]
fn compo_data_serde_bevy_native_component() {
let compo_orig = Transform::default();
let mut registry = TypeRegistry::default();
registry.register::<Transform>();
registry.register::<Vec3>();
registry.register::<Quat>();
registry.register_type_data::<Transform, ReflectFromReflect>();
registry.register_type_data::<Vec3, ReflectFromReflect>();
registry.register_type_data::<Quat, ReflectFromReflect>();
let data = reflect_to_bin(compo_orig.as_partial_reflect(), ®istry).unwrap();
let compo_result = bin_to_reflect(&data, ®istry);
let compo_result = compo_result.try_downcast::<Transform>().unwrap();
assert_eq!(*compo_result, compo_orig);
}
#[test]
fn material_serde() {
let material_orig = StandardMaterial {
base_color: Color::srgb(1.0, 0.0, 0.0),
..StandardMaterial::default()
};
let mut registry = TypeRegistry::default();
registry.register::<StandardMaterial>();
registry.register::<Color>();
registry.register::<Image>();
registry.register::<Handle<Image>>();
registry.register::<Option<Handle<Image>>>();
registry.register::<AlphaMode>();
registry.register::<ParallaxMappingMethod>();
registry.register::<OpaqueRendererMethod>();
registry.register_type_data::<StandardMaterial, ReflectFromReflect>();
let data = reflect_to_bin(material_orig.as_partial_reflect(), ®istry).unwrap();
let result = bin_to_reflect(&data, ®istry);
let result = result.try_downcast::<StandardMaterial>().unwrap();
assert_eq!(result.base_color, material_orig.base_color);
}
#[test]
fn reflect_material_no_dependencies() {
let compo = StandardMaterial {
base_color: Color::srgb(1.0, 0.0, 0.0),
..StandardMaterial::default()
};
let mut registry = TypeRegistry::default();
registry.register::<StandardMaterial>();
registry.register::<Color>();
registry.register::<Image>();
registry.register::<Handle<Image>>();
registry.register::<Option<Handle<Image>>>();
registry.register::<AlphaMode>();
registry.register::<ParallaxMappingMethod>();
registry.register::<OpaqueRendererMethod>();
let serializer = ReflectSerializer::new(compo.as_partial_reflect(), ®istry);
let result = bincode::serde::encode_to_vec(&serializer, BINCODE_OPTIONS).unwrap();
let result = bin_to_reflect(&result, ®istry);
let result = result.try_downcast::<StandardMaterial>().unwrap();
assert_eq!(compo.base_color, result.base_color);
}
}