Path: blob/main/crates/bevy_reflect/src/serde/ser/serializer.rs
6600 views
#[cfg(feature = "debug_stack")]1use crate::serde::ser::error_utils::TYPE_INFO_STACK;2use crate::{3serde::ser::{4arrays::ArraySerializer, custom_serialization::try_custom_serialize, enums::EnumSerializer,5error_utils::make_custom_error, lists::ListSerializer, maps::MapSerializer,6sets::SetSerializer, structs::StructSerializer, tuple_structs::TupleStructSerializer,7tuples::TupleSerializer,8},9PartialReflect, ReflectRef, TypeRegistry,10};11use serde::{ser::SerializeMap, Serialize, Serializer};1213use super::ReflectSerializerProcessor;1415/// A general purpose serializer for reflected types.16///17/// This is the serializer counterpart to [`ReflectDeserializer`].18///19/// See [`TypedReflectSerializer`] for a serializer that serializes a known type.20///21/// # Output22///23/// This serializer will output a map with a single entry,24/// where the key is the _full_ [type path] of the reflected type25/// and the value is the serialized data.26///27/// If you want to override serialization for specific values, you can pass in28/// a reference to a [`ReflectSerializerProcessor`] which will take priority29/// over all other serialization methods - see [`with_processor`].30///31/// # Example32///33/// ```34/// # use bevy_reflect::prelude::*;35/// # use bevy_reflect::{TypeRegistry, serde::ReflectSerializer};36/// #[derive(Reflect, PartialEq, Debug)]37/// #[type_path = "my_crate"]38/// struct MyStruct {39/// value: i3240/// }41///42/// let mut registry = TypeRegistry::default();43/// registry.register::<MyStruct>();44///45/// let input = MyStruct { value: 123 };46///47/// let reflect_serializer = ReflectSerializer::new(&input, ®istry);48/// let output = ron::to_string(&reflect_serializer).unwrap();49///50/// assert_eq!(output, r#"{"my_crate::MyStruct":(value:123)}"#);51/// ```52///53/// [`ReflectDeserializer`]: crate::serde::ReflectDeserializer54/// [type path]: crate::TypePath::type_path55/// [`with_processor`]: Self::with_processor56pub struct ReflectSerializer<'a, P = ()> {57value: &'a dyn PartialReflect,58registry: &'a TypeRegistry,59processor: Option<&'a P>,60}6162impl<'a> ReflectSerializer<'a, ()> {63/// Creates a serializer with no processor.64///65/// If you want to add custom logic for serializing certain values, use66/// [`with_processor`].67///68/// [`with_processor`]: Self::with_processor69pub fn new(value: &'a dyn PartialReflect, registry: &'a TypeRegistry) -> Self {70Self {71value,72registry,73processor: None,74}75}76}7778impl<'a, P: ReflectSerializerProcessor> ReflectSerializer<'a, P> {79/// Creates a serializer with a processor.80///81/// If you do not need any custom logic for handling certain values, use82/// [`new`].83///84/// [`new`]: Self::new85pub fn with_processor(86value: &'a dyn PartialReflect,87registry: &'a TypeRegistry,88processor: &'a P,89) -> Self {90Self {91value,92registry,93processor: Some(processor),94}95}96}9798impl<P: ReflectSerializerProcessor> Serialize for ReflectSerializer<'_, P> {99fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>100where101S: Serializer,102{103let mut state = serializer.serialize_map(Some(1))?;104state.serialize_entry(105self.value106.get_represented_type_info()107.ok_or_else(|| {108if self.value.is_dynamic() {109make_custom_error(format_args!(110"cannot serialize dynamic value without represented type: `{}`",111self.value.reflect_type_path()112))113} else {114make_custom_error(format_args!(115"cannot get type info for `{}`",116self.value.reflect_type_path()117))118}119})?120.type_path(),121&TypedReflectSerializer::new_internal(self.value, self.registry, self.processor),122)?;123state.end()124}125}126127/// A serializer for reflected types whose type will be known during deserialization.128///129/// This is the serializer counterpart to [`TypedReflectDeserializer`].130///131/// See [`ReflectSerializer`] for a serializer that serializes an unknown type.132///133/// # Output134///135/// Since the type is expected to be known during deserialization,136/// this serializer will not output any additional type information,137/// such as the [type path].138///139/// Instead, it will output just the serialized data.140///141/// If you want to override serialization for specific values, you can pass in142/// a reference to a [`ReflectSerializerProcessor`] which will take priority143/// over all other serialization methods - see [`with_processor`].144///145/// # Example146///147/// ```148/// # use bevy_reflect::prelude::*;149/// # use bevy_reflect::{TypeRegistry, serde::TypedReflectSerializer};150/// #[derive(Reflect, PartialEq, Debug)]151/// #[type_path = "my_crate"]152/// struct MyStruct {153/// value: i32154/// }155///156/// let mut registry = TypeRegistry::default();157/// registry.register::<MyStruct>();158///159/// let input = MyStruct { value: 123 };160///161/// let reflect_serializer = TypedReflectSerializer::new(&input, ®istry);162/// let output = ron::to_string(&reflect_serializer).unwrap();163///164/// assert_eq!(output, r#"(value:123)"#);165/// ```166///167/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer168/// [type path]: crate::TypePath::type_path169/// [`with_processor`]: Self::with_processor170pub struct TypedReflectSerializer<'a, P = ()> {171value: &'a dyn PartialReflect,172registry: &'a TypeRegistry,173processor: Option<&'a P>,174}175176impl<'a> TypedReflectSerializer<'a, ()> {177/// Creates a serializer with no processor.178///179/// If you want to add custom logic for serializing certain values, use180/// [`with_processor`].181///182/// [`with_processor`]: Self::with_processor183pub fn new(value: &'a dyn PartialReflect, registry: &'a TypeRegistry) -> Self {184#[cfg(feature = "debug_stack")]185TYPE_INFO_STACK.set(crate::type_info_stack::TypeInfoStack::new());186187Self {188value,189registry,190processor: None,191}192}193}194195impl<'a, P> TypedReflectSerializer<'a, P> {196/// Creates a serializer with a processor.197///198/// If you do not need any custom logic for handling certain values, use199/// [`new`].200///201/// [`new`]: Self::new202pub fn with_processor(203value: &'a dyn PartialReflect,204registry: &'a TypeRegistry,205processor: &'a P,206) -> Self {207#[cfg(feature = "debug_stack")]208TYPE_INFO_STACK.set(crate::type_info_stack::TypeInfoStack::new());209210Self {211value,212registry,213processor: Some(processor),214}215}216217/// An internal constructor for creating a serializer without resetting the type info stack.218pub(super) fn new_internal(219value: &'a dyn PartialReflect,220registry: &'a TypeRegistry,221processor: Option<&'a P>,222) -> Self {223Self {224value,225registry,226processor,227}228}229}230231impl<P: ReflectSerializerProcessor> Serialize for TypedReflectSerializer<'_, P> {232fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>233where234S: Serializer,235{236#[cfg(feature = "debug_stack")]237{238if let Some(info) = self.value.get_represented_type_info() {239TYPE_INFO_STACK.with_borrow_mut(|stack| stack.push(info));240}241}242243// First, check if our processor wants to serialize this type244// This takes priority over any other serialization operations245let serializer = if let Some(processor) = self.processor {246match processor.try_serialize(self.value, self.registry, serializer) {247Ok(Ok(value)) => {248return Ok(value);249}250Err(err) => {251return Err(make_custom_error(err));252}253Ok(Err(serializer)) => serializer,254}255} else {256serializer257};258259// Handle both Value case and types that have a custom `Serialize`260let (serializer, error) = match try_custom_serialize(self.value, self.registry, serializer)261{262Ok(result) => return result,263Err(value) => value,264};265266let output = match self.value.reflect_ref() {267ReflectRef::Struct(struct_value) => StructSerializer {268struct_value,269registry: self.registry,270processor: self.processor,271}272.serialize(serializer),273ReflectRef::TupleStruct(tuple_struct) => TupleStructSerializer {274tuple_struct,275registry: self.registry,276processor: self.processor,277}278.serialize(serializer),279ReflectRef::Tuple(tuple) => TupleSerializer {280tuple,281registry: self.registry,282processor: self.processor,283}284.serialize(serializer),285ReflectRef::List(list) => ListSerializer {286list,287registry: self.registry,288processor: self.processor,289}290.serialize(serializer),291ReflectRef::Array(array) => ArraySerializer {292array,293registry: self.registry,294processor: self.processor,295}296.serialize(serializer),297ReflectRef::Map(map) => MapSerializer {298map,299registry: self.registry,300processor: self.processor,301}302.serialize(serializer),303ReflectRef::Set(set) => SetSerializer {304set,305registry: self.registry,306processor: self.processor,307}308.serialize(serializer),309ReflectRef::Enum(enum_value) => EnumSerializer {310enum_value,311registry: self.registry,312processor: self.processor,313}314.serialize(serializer),315#[cfg(feature = "functions")]316ReflectRef::Function(_) => Err(make_custom_error("functions cannot be serialized")),317ReflectRef::Opaque(_) => Err(error),318};319320#[cfg(feature = "debug_stack")]321TYPE_INFO_STACK.with_borrow_mut(crate::type_info_stack::TypeInfoStack::pop);322323output324}325}326327328