Path: blob/main/crates/bevy_reflect/src/serde/ser/serialize_with_registry.rs
6600 views
use crate::{FromType, Reflect, TypeRegistry};1use alloc::boxed::Box;2use serde::{Serialize, Serializer};34/// Trait used to provide finer control when serializing a reflected type with one of5/// the reflection serializers.6///7/// This trait is the reflection equivalent of `serde`'s [`Serialize`] trait.8/// The main difference is that this trait provides access to the [`TypeRegistry`],9/// which means that we can use the registry and all its stored type information10/// to serialize our type.11///12/// This can be useful when writing a custom reflection serializer where we may13/// want to handle parts of the serialization process, but temporarily pass control14/// to the standard reflection serializer for other parts.15///16/// For the deserialization equivalent of this trait, see [`DeserializeWithRegistry`].17///18/// # Rationale19///20/// Without this trait and its associated [type data], such a serializer would have to21/// write out all of the serialization logic itself, possibly including22/// unnecessary code duplication and trivial implementations.23///24/// This is because a normal [`Serialize`] implementation has no knowledge of the25/// [`TypeRegistry`] and therefore cannot create a reflection-based serializer for26/// nested items.27///28/// # Implementors29///30/// In order for this to work with the reflection serializers like [`TypedReflectSerializer`]31/// and [`ReflectSerializer`], implementors should be sure to register the32/// [`ReflectSerializeWithRegistry`] type data.33/// This can be done [via the registry] or by adding `#[reflect(SerializeWithRegistry)]` to34/// the type definition.35///36/// [`DeserializeWithRegistry`]: crate::serde::DeserializeWithRegistry37/// [type data]: ReflectSerializeWithRegistry38/// [`TypedReflectSerializer`]: crate::serde::TypedReflectSerializer39/// [`ReflectSerializer`]: crate::serde::ReflectSerializer40/// [via the registry]: TypeRegistry::register_type_data41pub trait SerializeWithRegistry {42/// Serialize this value using the given [Serializer] and [`TypeRegistry`].43///44/// [`Serializer`]: ::serde::Serializer45fn serialize<S>(&self, serializer: S, registry: &TypeRegistry) -> Result<S::Ok, S::Error>46where47S: Serializer;48}4950/// Type data used to serialize a [`Reflect`] type with a custom [`SerializeWithRegistry`] implementation.51#[derive(Clone)]52pub struct ReflectSerializeWithRegistry {53serialize: for<'a> fn(54value: &'a dyn Reflect,55registry: &'a TypeRegistry,56) -> Box<dyn erased_serde::Serialize + 'a>,57}5859impl ReflectSerializeWithRegistry {60/// Serialize a [`Reflect`] type with this type data's custom [`SerializeWithRegistry`] implementation.61pub fn serialize<S>(62&self,63value: &dyn Reflect,64serializer: S,65registry: &TypeRegistry,66) -> Result<S::Ok, S::Error>67where68S: Serializer,69{70((self.serialize)(value, registry)).serialize(serializer)71}72}7374impl<T: Reflect + SerializeWithRegistry> FromType<T> for ReflectSerializeWithRegistry {75fn from_type() -> Self {76Self {77serialize: |value: &dyn Reflect, registry| {78let value = value.downcast_ref::<T>().unwrap_or_else(|| {79panic!(80"Expected value to be of type {} but received {}",81core::any::type_name::<T>(),82value.reflect_type_path()83)84});85Box::new(SerializableWithRegistry { value, registry })86},87}88}89}9091struct SerializableWithRegistry<'a, T: SerializeWithRegistry> {92value: &'a T,93registry: &'a TypeRegistry,94}9596impl<'a, T: SerializeWithRegistry> Serialize for SerializableWithRegistry<'a, T> {97fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>98where99S: Serializer,100{101self.value.serialize(serializer, self.registry)102}103}104105106