mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
bevy_reflect: Add ReflectSerializerProcessor
(#15548)
**NOTE: This is based on, and should be merged alongside, https://github.com/bevyengine/bevy/pull/15482.** I'll leave this in draft until that PR is merged. # Objective Equivalent of https://github.com/bevyengine/bevy/pull/15482 but for serialization. See that issue for the motivation. Also part of this tracking issue: https://github.com/bevyengine/bevy/issues/15518 This PR is non-breaking, just like the deserializer PR (because the new type parameter `P` has a default `P = ()`). ## Solution Identical solution to the deserializer PR. ## Testing Added unit tests and a very comprehensive doc test outlining a clear example and use case.
This commit is contained in:
parent
ded5ce27ae
commit
17c4b070ab
12 changed files with 628 additions and 138 deletions
|
@ -15,6 +15,8 @@ use crate::{PartialReflect, TypeRegistration, TypeRegistry};
|
||||||
/// deserializer and give back a [`Box<dyn PartialReflect>`], or return
|
/// deserializer and give back a [`Box<dyn PartialReflect>`], or return
|
||||||
/// ownership of the deserializer back, and continue with the default logic.
|
/// ownership of the deserializer back, and continue with the default logic.
|
||||||
///
|
///
|
||||||
|
/// The serialization equivalent of this is [`ReflectSerializerProcessor`].
|
||||||
|
///
|
||||||
/// # Compared to [`DeserializeWithRegistry`]
|
/// # Compared to [`DeserializeWithRegistry`]
|
||||||
///
|
///
|
||||||
/// [`DeserializeWithRegistry`] allows you to define how your type will be
|
/// [`DeserializeWithRegistry`] allows you to define how your type will be
|
||||||
|
@ -134,6 +136,7 @@ use crate::{PartialReflect, TypeRegistration, TypeRegistry};
|
||||||
/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer
|
/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer
|
||||||
/// [`try_deserialize`]: Self::try_deserialize
|
/// [`try_deserialize`]: Self::try_deserialize
|
||||||
/// [`DeserializeWithRegistry`]: crate::serde::DeserializeWithRegistry
|
/// [`DeserializeWithRegistry`]: crate::serde::DeserializeWithRegistry
|
||||||
|
/// [`ReflectSerializerProcessor`]: crate::serde::ReflectSerializerProcessor
|
||||||
pub trait ReflectDeserializerProcessor {
|
pub trait ReflectDeserializerProcessor {
|
||||||
/// Attempts to deserialize the value which a [`TypedReflectDeserializer`]
|
/// Attempts to deserialize the value which a [`TypedReflectDeserializer`]
|
||||||
/// is currently looking at, and knows the type of.
|
/// is currently looking at, and knows the type of.
|
||||||
|
|
|
@ -1,26 +1,27 @@
|
||||||
use crate::{serde::TypedReflectSerializer, Array, TypeRegistry};
|
use crate::{serde::TypedReflectSerializer, Array, TypeRegistry};
|
||||||
use serde::{ser::SerializeTuple, Serialize};
|
use serde::{ser::SerializeTuple, Serialize};
|
||||||
|
|
||||||
|
use super::ReflectSerializerProcessor;
|
||||||
|
|
||||||
/// A serializer for [`Array`] values.
|
/// A serializer for [`Array`] values.
|
||||||
pub(super) struct ArraySerializer<'a> {
|
pub(super) struct ArraySerializer<'a, P> {
|
||||||
array: &'a dyn Array,
|
pub array: &'a dyn Array,
|
||||||
registry: &'a TypeRegistry,
|
pub registry: &'a TypeRegistry,
|
||||||
|
pub processor: Option<&'a P>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ArraySerializer<'a> {
|
impl<P: ReflectSerializerProcessor> Serialize for ArraySerializer<'_, P> {
|
||||||
pub fn new(array: &'a dyn Array, registry: &'a TypeRegistry) -> Self {
|
|
||||||
Self { array, registry }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Serialize for ArraySerializer<'a> {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
{
|
{
|
||||||
let mut state = serializer.serialize_tuple(self.array.len())?;
|
let mut state = serializer.serialize_tuple(self.array.len())?;
|
||||||
for value in self.array.iter() {
|
for value in self.array.iter() {
|
||||||
state.serialize_element(&TypedReflectSerializer::new_internal(value, self.registry))?;
|
state.serialize_element(&TypedReflectSerializer::new_internal(
|
||||||
|
value,
|
||||||
|
self.registry,
|
||||||
|
self.processor,
|
||||||
|
))?;
|
||||||
}
|
}
|
||||||
state.end()
|
state.end()
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,22 +7,16 @@ use serde::{
|
||||||
Serialize,
|
Serialize,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::ReflectSerializerProcessor;
|
||||||
|
|
||||||
/// A serializer for [`Enum`] values.
|
/// A serializer for [`Enum`] values.
|
||||||
pub(super) struct EnumSerializer<'a> {
|
pub(super) struct EnumSerializer<'a, P> {
|
||||||
enum_value: &'a dyn Enum,
|
pub enum_value: &'a dyn Enum,
|
||||||
registry: &'a TypeRegistry,
|
pub registry: &'a TypeRegistry,
|
||||||
|
pub processor: Option<&'a P>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> EnumSerializer<'a> {
|
impl<P: ReflectSerializerProcessor> Serialize for EnumSerializer<'_, P> {
|
||||||
pub fn new(enum_value: &'a dyn Enum, registry: &'a TypeRegistry) -> Self {
|
|
||||||
Self {
|
|
||||||
enum_value,
|
|
||||||
registry,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Serialize for EnumSerializer<'a> {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
|
@ -86,7 +80,11 @@ impl<'a> Serialize for EnumSerializer<'a> {
|
||||||
let field_info = struct_info.field_at(index).unwrap();
|
let field_info = struct_info.field_at(index).unwrap();
|
||||||
state.serialize_field(
|
state.serialize_field(
|
||||||
field_info.name(),
|
field_info.name(),
|
||||||
&TypedReflectSerializer::new_internal(field.value(), self.registry),
|
&TypedReflectSerializer::new_internal(
|
||||||
|
field.value(),
|
||||||
|
self.registry,
|
||||||
|
self.processor,
|
||||||
|
),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
state.end()
|
state.end()
|
||||||
|
@ -97,14 +95,17 @@ impl<'a> Serialize for EnumSerializer<'a> {
|
||||||
if type_info.type_path_table().module_path() == Some("core::option")
|
if type_info.type_path_table().module_path() == Some("core::option")
|
||||||
&& type_info.type_path_table().ident() == Some("Option")
|
&& type_info.type_path_table().ident() == Some("Option")
|
||||||
{
|
{
|
||||||
serializer
|
serializer.serialize_some(&TypedReflectSerializer::new_internal(
|
||||||
.serialize_some(&TypedReflectSerializer::new_internal(field, self.registry))
|
field,
|
||||||
|
self.registry,
|
||||||
|
self.processor,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
serializer.serialize_newtype_variant(
|
serializer.serialize_newtype_variant(
|
||||||
enum_name,
|
enum_name,
|
||||||
variant_index,
|
variant_index,
|
||||||
variant_name,
|
variant_name,
|
||||||
&TypedReflectSerializer::new_internal(field, self.registry),
|
&TypedReflectSerializer::new_internal(field, self.registry, self.processor),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,6 +120,7 @@ impl<'a> Serialize for EnumSerializer<'a> {
|
||||||
state.serialize_field(&TypedReflectSerializer::new_internal(
|
state.serialize_field(&TypedReflectSerializer::new_internal(
|
||||||
field.value(),
|
field.value(),
|
||||||
self.registry,
|
self.registry,
|
||||||
|
self.processor,
|
||||||
))?;
|
))?;
|
||||||
}
|
}
|
||||||
state.end()
|
state.end()
|
||||||
|
|
|
@ -1,26 +1,27 @@
|
||||||
use crate::{serde::TypedReflectSerializer, List, TypeRegistry};
|
use crate::{serde::TypedReflectSerializer, List, TypeRegistry};
|
||||||
use serde::{ser::SerializeSeq, Serialize};
|
use serde::{ser::SerializeSeq, Serialize};
|
||||||
|
|
||||||
|
use super::ReflectSerializerProcessor;
|
||||||
|
|
||||||
/// A serializer for [`List`] values.
|
/// A serializer for [`List`] values.
|
||||||
pub(super) struct ListSerializer<'a> {
|
pub(super) struct ListSerializer<'a, P> {
|
||||||
list: &'a dyn List,
|
pub list: &'a dyn List,
|
||||||
registry: &'a TypeRegistry,
|
pub registry: &'a TypeRegistry,
|
||||||
|
pub processor: Option<&'a P>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ListSerializer<'a> {
|
impl<P: ReflectSerializerProcessor> Serialize for ListSerializer<'_, P> {
|
||||||
pub fn new(list: &'a dyn List, registry: &'a TypeRegistry) -> Self {
|
|
||||||
Self { list, registry }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Serialize for ListSerializer<'a> {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
{
|
{
|
||||||
let mut state = serializer.serialize_seq(Some(self.list.len()))?;
|
let mut state = serializer.serialize_seq(Some(self.list.len()))?;
|
||||||
for value in self.list.iter() {
|
for value in self.list.iter() {
|
||||||
state.serialize_element(&TypedReflectSerializer::new_internal(value, self.registry))?;
|
state.serialize_element(&TypedReflectSerializer::new_internal(
|
||||||
|
value,
|
||||||
|
self.registry,
|
||||||
|
self.processor,
|
||||||
|
))?;
|
||||||
}
|
}
|
||||||
state.end()
|
state.end()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
use crate::{serde::TypedReflectSerializer, Map, TypeRegistry};
|
use crate::{serde::TypedReflectSerializer, Map, TypeRegistry};
|
||||||
use serde::{ser::SerializeMap, Serialize};
|
use serde::{ser::SerializeMap, Serialize};
|
||||||
|
|
||||||
|
use super::ReflectSerializerProcessor;
|
||||||
|
|
||||||
/// A serializer for [`Map`] values.
|
/// A serializer for [`Map`] values.
|
||||||
pub(super) struct MapSerializer<'a> {
|
pub(super) struct MapSerializer<'a, P> {
|
||||||
map: &'a dyn Map,
|
pub map: &'a dyn Map,
|
||||||
registry: &'a TypeRegistry,
|
pub registry: &'a TypeRegistry,
|
||||||
|
pub processor: Option<&'a P>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MapSerializer<'a> {
|
impl<P: ReflectSerializerProcessor> Serialize for MapSerializer<'_, P> {
|
||||||
pub fn new(map: &'a dyn Map, registry: &'a TypeRegistry) -> Self {
|
|
||||||
Self { map, registry }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Serialize for MapSerializer<'a> {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
|
@ -21,8 +18,8 @@ impl<'a> Serialize for MapSerializer<'a> {
|
||||||
let mut state = serializer.serialize_map(Some(self.map.len()))?;
|
let mut state = serializer.serialize_map(Some(self.map.len()))?;
|
||||||
for (key, value) in self.map.iter() {
|
for (key, value) in self.map.iter() {
|
||||||
state.serialize_entry(
|
state.serialize_entry(
|
||||||
&TypedReflectSerializer::new_internal(key, self.registry),
|
&TypedReflectSerializer::new_internal(key, self.registry, self.processor),
|
||||||
&TypedReflectSerializer::new_internal(value, self.registry),
|
&TypedReflectSerializer::new_internal(value, self.registry, self.processor),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
state.end()
|
state.end()
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub use processor::*;
|
||||||
pub use serializable::*;
|
pub use serializable::*;
|
||||||
pub use serialize_with_registry::*;
|
pub use serialize_with_registry::*;
|
||||||
pub use serializer::*;
|
pub use serializer::*;
|
||||||
|
@ -8,6 +9,7 @@ mod enums;
|
||||||
mod error_utils;
|
mod error_utils;
|
||||||
mod lists;
|
mod lists;
|
||||||
mod maps;
|
mod maps;
|
||||||
|
mod processor;
|
||||||
mod serializable;
|
mod serializable;
|
||||||
mod serialize_with_registry;
|
mod serialize_with_registry;
|
||||||
mod serializer;
|
mod serializer;
|
||||||
|
@ -19,13 +21,15 @@ mod tuples;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
self as bevy_reflect, serde::ReflectSerializer, PartialReflect, Reflect, ReflectSerialize,
|
self as bevy_reflect,
|
||||||
Struct, TypeRegistry,
|
serde::{ReflectSerializer, ReflectSerializerProcessor},
|
||||||
|
PartialReflect, Reflect, ReflectSerialize, Struct, TypeRegistry,
|
||||||
};
|
};
|
||||||
use bevy_utils::{HashMap, HashSet};
|
use bevy_utils::{HashMap, HashSet};
|
||||||
|
use core::any::TypeId;
|
||||||
use core::{f32::consts::PI, ops::RangeInclusive};
|
use core::{f32::consts::PI, ops::RangeInclusive};
|
||||||
use ron::{extensions::Extensions, ser::PrettyConfig};
|
use ron::{extensions::Extensions, ser::PrettyConfig};
|
||||||
use serde::Serialize;
|
use serde::{Serialize, Serializer};
|
||||||
|
|
||||||
#[derive(Reflect, Debug, PartialEq)]
|
#[derive(Reflect, Debug, PartialEq)]
|
||||||
struct MyStruct {
|
struct MyStruct {
|
||||||
|
@ -474,6 +478,172 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_use_processor_for_custom_serialization() {
|
||||||
|
#[derive(Reflect, Debug, PartialEq)]
|
||||||
|
struct Foo {
|
||||||
|
bar: i32,
|
||||||
|
qux: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FooProcessor;
|
||||||
|
|
||||||
|
impl ReflectSerializerProcessor for FooProcessor {
|
||||||
|
fn try_serialize<S>(
|
||||||
|
&self,
|
||||||
|
value: &dyn PartialReflect,
|
||||||
|
_: &TypeRegistry,
|
||||||
|
serializer: S,
|
||||||
|
) -> Result<Result<S::Ok, S>, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let Some(value) = value.try_as_reflect() else {
|
||||||
|
return Ok(Err(serializer));
|
||||||
|
};
|
||||||
|
|
||||||
|
let type_id = value.reflect_type_info().type_id();
|
||||||
|
if type_id == TypeId::of::<i64>() {
|
||||||
|
Ok(Ok(serializer.serialize_str("custom!")?))
|
||||||
|
} else {
|
||||||
|
Ok(Err(serializer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = Foo { bar: 123, qux: 456 };
|
||||||
|
|
||||||
|
let mut registry = TypeRegistry::new();
|
||||||
|
registry.register::<Foo>();
|
||||||
|
|
||||||
|
let processor = FooProcessor;
|
||||||
|
let serializer = ReflectSerializer::with_processor(&value, ®istry, &processor);
|
||||||
|
|
||||||
|
let config = PrettyConfig::default().new_line(String::from("\n"));
|
||||||
|
let output = ron::ser::to_string_pretty(&serializer, config).unwrap();
|
||||||
|
|
||||||
|
let expected = r#"{
|
||||||
|
"bevy_reflect::serde::ser::tests::Foo": (
|
||||||
|
bar: 123,
|
||||||
|
qux: "custom!",
|
||||||
|
),
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
assert_eq!(expected, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_use_processor_for_multiple_registrations() {
|
||||||
|
#[derive(Reflect, Debug, PartialEq)]
|
||||||
|
struct Foo {
|
||||||
|
bar: i32,
|
||||||
|
sub: SubFoo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Reflect, Debug, PartialEq)]
|
||||||
|
struct SubFoo {
|
||||||
|
val: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FooProcessor;
|
||||||
|
|
||||||
|
impl ReflectSerializerProcessor for FooProcessor {
|
||||||
|
fn try_serialize<S>(
|
||||||
|
&self,
|
||||||
|
value: &dyn PartialReflect,
|
||||||
|
_: &TypeRegistry,
|
||||||
|
serializer: S,
|
||||||
|
) -> Result<Result<S::Ok, S>, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let Some(value) = value.try_as_reflect() else {
|
||||||
|
return Ok(Err(serializer));
|
||||||
|
};
|
||||||
|
|
||||||
|
let type_id = value.reflect_type_info().type_id();
|
||||||
|
if type_id == TypeId::of::<i32>() {
|
||||||
|
Ok(Ok(serializer.serialize_str("an i32")?))
|
||||||
|
} else if type_id == TypeId::of::<SubFoo>() {
|
||||||
|
Ok(Ok(serializer.serialize_str("a SubFoo")?))
|
||||||
|
} else {
|
||||||
|
Ok(Err(serializer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = Foo {
|
||||||
|
bar: 123,
|
||||||
|
sub: SubFoo { val: 456 },
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut registry = TypeRegistry::new();
|
||||||
|
registry.register::<Foo>();
|
||||||
|
registry.register::<SubFoo>();
|
||||||
|
|
||||||
|
let processor = FooProcessor;
|
||||||
|
let serializer = ReflectSerializer::with_processor(&value, ®istry, &processor);
|
||||||
|
|
||||||
|
let config = PrettyConfig::default().new_line(String::from("\n"));
|
||||||
|
let output = ron::ser::to_string_pretty(&serializer, config).unwrap();
|
||||||
|
|
||||||
|
let expected = r#"{
|
||||||
|
"bevy_reflect::serde::ser::tests::Foo": (
|
||||||
|
bar: "an i32",
|
||||||
|
sub: "a SubFoo",
|
||||||
|
),
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
assert_eq!(expected, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_propagate_processor_serialize_error() {
|
||||||
|
struct ErroringProcessor;
|
||||||
|
|
||||||
|
impl ReflectSerializerProcessor for ErroringProcessor {
|
||||||
|
fn try_serialize<S>(
|
||||||
|
&self,
|
||||||
|
value: &dyn PartialReflect,
|
||||||
|
_: &TypeRegistry,
|
||||||
|
serializer: S,
|
||||||
|
) -> Result<Result<S::Ok, S>, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let Some(value) = value.try_as_reflect() else {
|
||||||
|
return Ok(Err(serializer));
|
||||||
|
};
|
||||||
|
|
||||||
|
let type_id = value.reflect_type_info().type_id();
|
||||||
|
if type_id == TypeId::of::<i32>() {
|
||||||
|
Err(serde::ser::Error::custom("my custom serialize error"))
|
||||||
|
} else {
|
||||||
|
Ok(Err(serializer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = 123_i32;
|
||||||
|
|
||||||
|
let registry = TypeRegistry::new();
|
||||||
|
|
||||||
|
let processor = ErroringProcessor;
|
||||||
|
let serializer = ReflectSerializer::with_processor(&value, ®istry, &processor);
|
||||||
|
let error = ron::ser::to_string_pretty(&serializer, PrettyConfig::default()).unwrap_err();
|
||||||
|
|
||||||
|
#[cfg(feature = "debug_stack")]
|
||||||
|
assert_eq!(
|
||||||
|
error,
|
||||||
|
ron::Error::Message("my custom serialize error (stack: `i32`)".to_string())
|
||||||
|
);
|
||||||
|
#[cfg(not(feature = "debug_stack"))]
|
||||||
|
assert_eq!(
|
||||||
|
error,
|
||||||
|
ron::Error::Message("my custom serialize error".to_string())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "functions")]
|
#[cfg(feature = "functions")]
|
||||||
mod functions {
|
mod functions {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
196
crates/bevy_reflect/src/serde/ser/processor.rs
Normal file
196
crates/bevy_reflect/src/serde/ser/processor.rs
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
use serde::Serializer;
|
||||||
|
|
||||||
|
use crate::{PartialReflect, TypeRegistry};
|
||||||
|
|
||||||
|
/// Allows overriding the default serialization behavior of
|
||||||
|
/// [`ReflectSerializer`] and [`TypedReflectSerializer`] for specific values.
|
||||||
|
///
|
||||||
|
/// When serializing a reflected value, you may want to override the default
|
||||||
|
/// behavior and use your own logic for serialization. This logic may also be
|
||||||
|
/// context-dependent, and only apply for a single use of your
|
||||||
|
/// [`ReflectSerializer`]. To achieve this, you can create a processor and pass
|
||||||
|
/// it into your serializer.
|
||||||
|
///
|
||||||
|
/// Whenever the serializer attempts to serialize a value, it will first call
|
||||||
|
/// [`try_serialize`] on your processor, which may take ownership of the
|
||||||
|
/// serializer and write into the serializer (successfully or not), or return
|
||||||
|
/// ownership of the serializer back, and continue with the default logic.
|
||||||
|
///
|
||||||
|
/// The deserialization equivalent of this is [`ReflectDeserializerProcessor`].
|
||||||
|
///
|
||||||
|
/// # Compared to [`SerializeWithRegistry`]
|
||||||
|
///
|
||||||
|
/// [`SerializeWithRegistry`] allows you to define how your type will be
|
||||||
|
/// serialized by a [`TypedReflectSerializer`], given the extra context of the
|
||||||
|
/// [`TypeRegistry`]. If your type can be serialized entirely using that, then
|
||||||
|
/// you should prefer implementing that trait instead of using a processor.
|
||||||
|
///
|
||||||
|
/// However, you may need more context-dependent data which is only present in
|
||||||
|
/// the scope where you create the [`TypedReflectSerializer`]. For example, if
|
||||||
|
/// you need to use a reference to a value while serializing, then there is no
|
||||||
|
/// way to do this with [`SerializeWithRegistry`] as you can't pass that
|
||||||
|
/// reference into anywhere. This is where a processor is useful, as the
|
||||||
|
/// processor can capture local variables.
|
||||||
|
///
|
||||||
|
/// A [`ReflectSerializerProcessor`] always takes priority over a
|
||||||
|
/// [`SerializeWithRegistry`] implementation, so this is also useful for
|
||||||
|
/// overriding serialization behavior if you need to do something custom.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Serializing a reflected value when saving an asset to disk, and replacing
|
||||||
|
/// asset handles with the handle path (if it has one):
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use core::any::Any;
|
||||||
|
/// # use serde::Serialize;
|
||||||
|
/// # use bevy_reflect::{PartialReflect, Reflect, TypeData, TypeRegistry};
|
||||||
|
/// # use bevy_reflect::serde::{ReflectSerializer, ReflectSerializerProcessor};
|
||||||
|
/// #
|
||||||
|
/// # #[derive(Debug, Clone, Reflect)]
|
||||||
|
/// # struct Handle<T>(T);
|
||||||
|
/// # #[derive(Debug, Clone, Reflect)]
|
||||||
|
/// # struct Mesh;
|
||||||
|
/// #
|
||||||
|
/// # struct ReflectHandle;
|
||||||
|
/// # impl TypeData for ReflectHandle {
|
||||||
|
/// # fn clone_type_data(&self) -> Box<dyn TypeData> {
|
||||||
|
/// # unimplemented!()
|
||||||
|
/// # }
|
||||||
|
/// # }
|
||||||
|
/// # impl ReflectHandle {
|
||||||
|
/// # fn downcast_handle_untyped(&self, handle: &(dyn Any + 'static)) -> Option<UntypedHandle> {
|
||||||
|
/// # unimplemented!()
|
||||||
|
/// # }
|
||||||
|
/// # }
|
||||||
|
/// #
|
||||||
|
/// # #[derive(Debug, Clone)]
|
||||||
|
/// # struct UntypedHandle;
|
||||||
|
/// # impl UntypedHandle {
|
||||||
|
/// # fn path(&self) -> Option<&str> {
|
||||||
|
/// # unimplemented!()
|
||||||
|
/// # }
|
||||||
|
/// # }
|
||||||
|
/// # type AssetError = Box<dyn core::error::Error>;
|
||||||
|
/// #
|
||||||
|
/// #[derive(Debug, Clone, Reflect)]
|
||||||
|
/// struct MyAsset {
|
||||||
|
/// name: String,
|
||||||
|
/// mesh: Handle<Mesh>,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// struct HandleProcessor;
|
||||||
|
///
|
||||||
|
/// impl ReflectSerializerProcessor for HandleProcessor {
|
||||||
|
/// fn try_serialize<S>(
|
||||||
|
/// &self,
|
||||||
|
/// value: &dyn PartialReflect,
|
||||||
|
/// registry: &TypeRegistry,
|
||||||
|
/// serializer: S,
|
||||||
|
/// ) -> Result<Result<S::Ok, S>, S::Error>
|
||||||
|
/// where
|
||||||
|
/// S: serde::Serializer,
|
||||||
|
/// {
|
||||||
|
/// let Some(value) = value.try_as_reflect() else {
|
||||||
|
/// // we don't have any info on this type; do the default serialization logic
|
||||||
|
/// return Ok(Err(serializer));
|
||||||
|
/// };
|
||||||
|
/// let type_id = value.reflect_type_info().type_id();
|
||||||
|
/// let Some(reflect_handle) = registry.get_type_data::<ReflectHandle>(type_id) else {
|
||||||
|
/// // this isn't a `Handle<T>`
|
||||||
|
/// return Ok(Err(serializer));
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// let untyped_handle = reflect_handle
|
||||||
|
/// .downcast_handle_untyped(value.as_any())
|
||||||
|
/// .unwrap();
|
||||||
|
/// if let Some(path) = untyped_handle.path() {
|
||||||
|
/// Ok(Ok(serializer.serialize_str(path)?))
|
||||||
|
/// } else {
|
||||||
|
/// Ok(Ok(serializer.serialize_unit()?))
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn save(type_registry: &TypeRegistry, asset: &MyAsset) -> Result<Vec<u8>, AssetError> {
|
||||||
|
/// let mut asset_bytes = Vec::new();
|
||||||
|
///
|
||||||
|
/// let processor = HandleProcessor;
|
||||||
|
/// let serializer = ReflectSerializer::with_processor(asset, type_registry, &processor);
|
||||||
|
/// let mut ron_serializer = ron::Serializer::new(&mut asset_bytes, None)?;
|
||||||
|
///
|
||||||
|
/// serializer.serialize(&mut ron_serializer)?;
|
||||||
|
/// Ok(asset_bytes)
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [`ReflectSerializer`]: crate::serde::ReflectSerializer
|
||||||
|
/// [`TypedReflectSerializer`]: crate::serde::TypedReflectSerializer
|
||||||
|
/// [`try_serialize`]: Self::try_serialize
|
||||||
|
/// [`SerializeWithRegistry`]: crate::serde::SerializeWithRegistry
|
||||||
|
/// [`ReflectDeserializerProcessor`]: crate::serde::ReflectDeserializerProcessor
|
||||||
|
pub trait ReflectSerializerProcessor {
|
||||||
|
/// Attempts to serialize the value which a [`TypedReflectSerializer`] is
|
||||||
|
/// currently looking at.
|
||||||
|
///
|
||||||
|
/// If you want to override the default serialization, return
|
||||||
|
/// `Ok(Ok(value))` with an `Ok` output from the serializer.
|
||||||
|
///
|
||||||
|
/// If you don't want to override the serialization, return ownership of
|
||||||
|
/// the serializer back via `Ok(Err(serializer))`.
|
||||||
|
///
|
||||||
|
/// You can use the type registry to read info about the type you're
|
||||||
|
/// serializing, or just try to downcast the value directly:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use bevy_reflect::{TypeRegistration, TypeRegistry, PartialReflect};
|
||||||
|
/// # use bevy_reflect::serde::ReflectSerializerProcessor;
|
||||||
|
/// # use core::any::TypeId;
|
||||||
|
/// struct I32AsStringProcessor;
|
||||||
|
///
|
||||||
|
/// impl ReflectSerializerProcessor for I32AsStringProcessor {
|
||||||
|
/// fn try_serialize<S>(
|
||||||
|
/// &self,
|
||||||
|
/// value: &dyn PartialReflect,
|
||||||
|
/// registry: &TypeRegistry,
|
||||||
|
/// serializer: S,
|
||||||
|
/// ) -> Result<Result<S::Ok, S>, S::Error>
|
||||||
|
/// where
|
||||||
|
/// S: serde::Serializer
|
||||||
|
/// {
|
||||||
|
/// if let Some(value) = value.try_downcast_ref::<i32>() {
|
||||||
|
/// let value_as_string = format!("{value:?}");
|
||||||
|
/// Ok(Ok(serializer.serialize_str(&value_as_string)?))
|
||||||
|
/// } else {
|
||||||
|
/// // Not an `i32`, just do the default serialization
|
||||||
|
/// Ok(Err(serializer))
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [`TypedReflectSerializer`]: crate::serde::TypedReflectSerializer
|
||||||
|
/// [`Reflect`]: crate::Reflect
|
||||||
|
fn try_serialize<S>(
|
||||||
|
&self,
|
||||||
|
value: &dyn PartialReflect,
|
||||||
|
registry: &TypeRegistry,
|
||||||
|
serializer: S,
|
||||||
|
) -> Result<Result<S::Ok, S>, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReflectSerializerProcessor for () {
|
||||||
|
fn try_serialize<S>(
|
||||||
|
&self,
|
||||||
|
_value: &dyn PartialReflect,
|
||||||
|
_registry: &TypeRegistry,
|
||||||
|
serializer: S,
|
||||||
|
) -> Result<Result<S::Ok, S>, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
Ok(Err(serializer))
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,9 @@ use crate::{
|
||||||
},
|
},
|
||||||
PartialReflect, ReflectRef, TypeRegistry,
|
PartialReflect, ReflectRef, TypeRegistry,
|
||||||
};
|
};
|
||||||
use serde::{ser::SerializeMap, Serialize};
|
use serde::{ser::SerializeMap, Serialize, Serializer};
|
||||||
|
|
||||||
|
use super::ReflectSerializerProcessor;
|
||||||
|
|
||||||
/// A general purpose serializer for reflected types.
|
/// A general purpose serializer for reflected types.
|
||||||
///
|
///
|
||||||
|
@ -23,6 +25,10 @@ use serde::{ser::SerializeMap, Serialize};
|
||||||
/// where the key is the _full_ [type path] of the reflected type
|
/// where the key is the _full_ [type path] of the reflected type
|
||||||
/// and the value is the serialized data.
|
/// and the value is the serialized data.
|
||||||
///
|
///
|
||||||
|
/// If you want to override serialization for specific values, you can pass in
|
||||||
|
/// a reference to a [`ReflectSerializerProcessor`] which will take priority
|
||||||
|
/// over all other serialization methods - see [`with_processor`].
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -47,21 +53,53 @@ use serde::{ser::SerializeMap, Serialize};
|
||||||
///
|
///
|
||||||
/// [`ReflectDeserializer`]: crate::serde::ReflectDeserializer
|
/// [`ReflectDeserializer`]: crate::serde::ReflectDeserializer
|
||||||
/// [type path]: crate::TypePath::type_path
|
/// [type path]: crate::TypePath::type_path
|
||||||
pub struct ReflectSerializer<'a> {
|
/// [`with_processor`]: Self::with_processor
|
||||||
|
pub struct ReflectSerializer<'a, P = ()> {
|
||||||
value: &'a dyn PartialReflect,
|
value: &'a dyn PartialReflect,
|
||||||
registry: &'a TypeRegistry,
|
registry: &'a TypeRegistry,
|
||||||
|
processor: Option<&'a P>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ReflectSerializer<'a> {
|
impl<'a> ReflectSerializer<'a, ()> {
|
||||||
|
/// Creates a serializer with no processor.
|
||||||
|
///
|
||||||
|
/// If you want to add custom logic for serializing certain values, use
|
||||||
|
/// [`with_processor`].
|
||||||
|
///
|
||||||
|
/// [`with_processor`]: Self::with_processor
|
||||||
pub fn new(value: &'a dyn PartialReflect, registry: &'a TypeRegistry) -> Self {
|
pub fn new(value: &'a dyn PartialReflect, registry: &'a TypeRegistry) -> Self {
|
||||||
Self { value, registry }
|
Self {
|
||||||
|
value,
|
||||||
|
registry,
|
||||||
|
processor: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Serialize for ReflectSerializer<'a> {
|
impl<'a, P: ReflectSerializerProcessor> ReflectSerializer<'a, P> {
|
||||||
|
/// Creates a serializer with a processor.
|
||||||
|
///
|
||||||
|
/// If you do not need any custom logic for handling certain values, use
|
||||||
|
/// [`new`].
|
||||||
|
///
|
||||||
|
/// [`new`]: Self::new
|
||||||
|
pub fn with_processor(
|
||||||
|
value: &'a dyn PartialReflect,
|
||||||
|
registry: &'a TypeRegistry,
|
||||||
|
processor: &'a P,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
value,
|
||||||
|
registry,
|
||||||
|
processor: Some(processor),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: ReflectSerializerProcessor> Serialize for ReflectSerializer<'_, P> {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
let mut state = serializer.serialize_map(Some(1))?;
|
let mut state = serializer.serialize_map(Some(1))?;
|
||||||
state.serialize_entry(
|
state.serialize_entry(
|
||||||
|
@ -81,7 +119,7 @@ impl<'a> Serialize for ReflectSerializer<'a> {
|
||||||
}
|
}
|
||||||
})?
|
})?
|
||||||
.type_path(),
|
.type_path(),
|
||||||
&TypedReflectSerializer::new(self.value, self.registry),
|
&TypedReflectSerializer::new_internal(self.value, self.registry, self.processor),
|
||||||
)?;
|
)?;
|
||||||
state.end()
|
state.end()
|
||||||
}
|
}
|
||||||
|
@ -101,6 +139,10 @@ impl<'a> Serialize for ReflectSerializer<'a> {
|
||||||
///
|
///
|
||||||
/// Instead, it will output just the serialized data.
|
/// Instead, it will output just the serialized data.
|
||||||
///
|
///
|
||||||
|
/// If you want to override serialization for specific values, you can pass in
|
||||||
|
/// a reference to a [`ReflectSerializerProcessor`] which will take priority
|
||||||
|
/// over all other serialization methods - see [`with_processor`].
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -125,29 +167,72 @@ impl<'a> Serialize for ReflectSerializer<'a> {
|
||||||
///
|
///
|
||||||
/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer
|
/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer
|
||||||
/// [type path]: crate::TypePath::type_path
|
/// [type path]: crate::TypePath::type_path
|
||||||
pub struct TypedReflectSerializer<'a> {
|
/// [`with_processor`]: Self::with_processor
|
||||||
|
pub struct TypedReflectSerializer<'a, P = ()> {
|
||||||
value: &'a dyn PartialReflect,
|
value: &'a dyn PartialReflect,
|
||||||
registry: &'a TypeRegistry,
|
registry: &'a TypeRegistry,
|
||||||
|
processor: Option<&'a P>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TypedReflectSerializer<'a> {
|
impl<'a> TypedReflectSerializer<'a, ()> {
|
||||||
|
/// Creates a serializer with no processor.
|
||||||
|
///
|
||||||
|
/// If you want to add custom logic for serializing certain values, use
|
||||||
|
/// [`with_processor`].
|
||||||
|
///
|
||||||
|
/// [`with_processor`]: Self::with_processor
|
||||||
pub fn new(value: &'a dyn PartialReflect, registry: &'a TypeRegistry) -> Self {
|
pub fn new(value: &'a dyn PartialReflect, registry: &'a TypeRegistry) -> Self {
|
||||||
#[cfg(feature = "debug_stack")]
|
#[cfg(feature = "debug_stack")]
|
||||||
TYPE_INFO_STACK.set(crate::type_info_stack::TypeInfoStack::new());
|
TYPE_INFO_STACK.set(crate::type_info_stack::TypeInfoStack::new());
|
||||||
|
|
||||||
Self { value, registry }
|
Self {
|
||||||
}
|
value,
|
||||||
|
registry,
|
||||||
/// An internal constructor for creating a serializer without resetting the type info stack.
|
processor: None,
|
||||||
pub(super) fn new_internal(value: &'a dyn PartialReflect, registry: &'a TypeRegistry) -> Self {
|
}
|
||||||
Self { value, registry }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Serialize for TypedReflectSerializer<'a> {
|
impl<'a, P> TypedReflectSerializer<'a, P> {
|
||||||
|
/// Creates a serializer with a processor.
|
||||||
|
///
|
||||||
|
/// If you do not need any custom logic for handling certain values, use
|
||||||
|
/// [`new`].
|
||||||
|
///
|
||||||
|
/// [`new`]: Self::new
|
||||||
|
pub fn with_processor(
|
||||||
|
value: &'a dyn PartialReflect,
|
||||||
|
registry: &'a TypeRegistry,
|
||||||
|
processor: &'a P,
|
||||||
|
) -> Self {
|
||||||
|
#[cfg(feature = "debug_stack")]
|
||||||
|
TYPE_INFO_STACK.set(crate::type_info_stack::TypeInfoStack::new());
|
||||||
|
|
||||||
|
Self {
|
||||||
|
value,
|
||||||
|
registry,
|
||||||
|
processor: Some(processor),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An internal constructor for creating a serializer without resetting the type info stack.
|
||||||
|
pub(super) fn new_internal(
|
||||||
|
value: &'a dyn PartialReflect,
|
||||||
|
registry: &'a TypeRegistry,
|
||||||
|
processor: Option<&'a P>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
value,
|
||||||
|
registry,
|
||||||
|
processor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: ReflectSerializerProcessor> Serialize for TypedReflectSerializer<'_, P> {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
#[cfg(feature = "debug_stack")]
|
#[cfg(feature = "debug_stack")]
|
||||||
{
|
{
|
||||||
|
@ -155,6 +240,23 @@ impl<'a> Serialize for TypedReflectSerializer<'a> {
|
||||||
TYPE_INFO_STACK.with_borrow_mut(|stack| stack.push(info));
|
TYPE_INFO_STACK.with_borrow_mut(|stack| stack.push(info));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// First, check if our processor wants to serialize this type
|
||||||
|
// This takes priority over any other serialization operations
|
||||||
|
let serializer = if let Some(processor) = self.processor {
|
||||||
|
match processor.try_serialize(self.value, self.registry, serializer) {
|
||||||
|
Ok(Ok(value)) => {
|
||||||
|
return Ok(value);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
return Err(make_custom_error(err));
|
||||||
|
}
|
||||||
|
Ok(Err(serializer)) => serializer,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
serializer
|
||||||
|
};
|
||||||
|
|
||||||
// Handle both Value case and types that have a custom `Serialize`
|
// Handle both Value case and types that have a custom `Serialize`
|
||||||
let (serializer, error) = match try_custom_serialize(self.value, self.registry, serializer)
|
let (serializer, error) = match try_custom_serialize(self.value, self.registry, serializer)
|
||||||
{
|
{
|
||||||
|
@ -163,30 +265,54 @@ impl<'a> Serialize for TypedReflectSerializer<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let output = match self.value.reflect_ref() {
|
let output = match self.value.reflect_ref() {
|
||||||
ReflectRef::Struct(value) => {
|
ReflectRef::Struct(struct_value) => StructSerializer {
|
||||||
StructSerializer::new(value, self.registry).serialize(serializer)
|
struct_value,
|
||||||
|
registry: self.registry,
|
||||||
|
processor: self.processor,
|
||||||
}
|
}
|
||||||
ReflectRef::TupleStruct(value) => {
|
.serialize(serializer),
|
||||||
TupleStructSerializer::new(value, self.registry).serialize(serializer)
|
ReflectRef::TupleStruct(tuple_struct) => TupleStructSerializer {
|
||||||
|
tuple_struct,
|
||||||
|
registry: self.registry,
|
||||||
|
processor: self.processor,
|
||||||
}
|
}
|
||||||
ReflectRef::Tuple(value) => {
|
.serialize(serializer),
|
||||||
TupleSerializer::new(value, self.registry).serialize(serializer)
|
ReflectRef::Tuple(tuple) => TupleSerializer {
|
||||||
|
tuple,
|
||||||
|
registry: self.registry,
|
||||||
|
processor: self.processor,
|
||||||
}
|
}
|
||||||
ReflectRef::List(value) => {
|
.serialize(serializer),
|
||||||
ListSerializer::new(value, self.registry).serialize(serializer)
|
ReflectRef::List(list) => ListSerializer {
|
||||||
|
list,
|
||||||
|
registry: self.registry,
|
||||||
|
processor: self.processor,
|
||||||
}
|
}
|
||||||
ReflectRef::Array(value) => {
|
.serialize(serializer),
|
||||||
ArraySerializer::new(value, self.registry).serialize(serializer)
|
ReflectRef::Array(array) => ArraySerializer {
|
||||||
|
array,
|
||||||
|
registry: self.registry,
|
||||||
|
processor: self.processor,
|
||||||
}
|
}
|
||||||
ReflectRef::Map(value) => {
|
.serialize(serializer),
|
||||||
MapSerializer::new(value, self.registry).serialize(serializer)
|
ReflectRef::Map(map) => MapSerializer {
|
||||||
|
map,
|
||||||
|
registry: self.registry,
|
||||||
|
processor: self.processor,
|
||||||
}
|
}
|
||||||
ReflectRef::Set(value) => {
|
.serialize(serializer),
|
||||||
SetSerializer::new(value, self.registry).serialize(serializer)
|
ReflectRef::Set(set) => SetSerializer {
|
||||||
|
set,
|
||||||
|
registry: self.registry,
|
||||||
|
processor: self.processor,
|
||||||
}
|
}
|
||||||
ReflectRef::Enum(value) => {
|
.serialize(serializer),
|
||||||
EnumSerializer::new(value, self.registry).serialize(serializer)
|
ReflectRef::Enum(enum_value) => EnumSerializer {
|
||||||
|
enum_value,
|
||||||
|
registry: self.registry,
|
||||||
|
processor: self.processor,
|
||||||
}
|
}
|
||||||
|
.serialize(serializer),
|
||||||
#[cfg(feature = "functions")]
|
#[cfg(feature = "functions")]
|
||||||
ReflectRef::Function(_) => Err(make_custom_error("functions cannot be serialized")),
|
ReflectRef::Function(_) => Err(make_custom_error("functions cannot be serialized")),
|
||||||
ReflectRef::Opaque(_) => Err(error),
|
ReflectRef::Opaque(_) => Err(error),
|
||||||
|
|
|
@ -1,26 +1,27 @@
|
||||||
use crate::{serde::TypedReflectSerializer, Set, TypeRegistry};
|
use crate::{serde::TypedReflectSerializer, Set, TypeRegistry};
|
||||||
use serde::{ser::SerializeSeq, Serialize};
|
use serde::{ser::SerializeSeq, Serialize};
|
||||||
|
|
||||||
|
use super::ReflectSerializerProcessor;
|
||||||
|
|
||||||
/// A serializer for [`Set`] values.
|
/// A serializer for [`Set`] values.
|
||||||
pub(super) struct SetSerializer<'a> {
|
pub(super) struct SetSerializer<'a, P> {
|
||||||
set: &'a dyn Set,
|
pub set: &'a dyn Set,
|
||||||
registry: &'a TypeRegistry,
|
pub registry: &'a TypeRegistry,
|
||||||
|
pub processor: Option<&'a P>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SetSerializer<'a> {
|
impl<P: ReflectSerializerProcessor> Serialize for SetSerializer<'_, P> {
|
||||||
pub fn new(set: &'a dyn Set, registry: &'a TypeRegistry) -> Self {
|
|
||||||
Self { set, registry }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Serialize for SetSerializer<'a> {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
{
|
{
|
||||||
let mut state = serializer.serialize_seq(Some(self.set.len()))?;
|
let mut state = serializer.serialize_seq(Some(self.set.len()))?;
|
||||||
for value in self.set.iter() {
|
for value in self.set.iter() {
|
||||||
state.serialize_element(&TypedReflectSerializer::new_internal(value, self.registry))?;
|
state.serialize_element(&TypedReflectSerializer::new_internal(
|
||||||
|
value,
|
||||||
|
self.registry,
|
||||||
|
self.processor,
|
||||||
|
))?;
|
||||||
}
|
}
|
||||||
state.end()
|
state.end()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,22 +4,16 @@ use crate::{
|
||||||
};
|
};
|
||||||
use serde::{ser::SerializeStruct, Serialize};
|
use serde::{ser::SerializeStruct, Serialize};
|
||||||
|
|
||||||
|
use super::ReflectSerializerProcessor;
|
||||||
|
|
||||||
/// A serializer for [`Struct`] values.
|
/// A serializer for [`Struct`] values.
|
||||||
pub(super) struct StructSerializer<'a> {
|
pub(super) struct StructSerializer<'a, P> {
|
||||||
struct_value: &'a dyn Struct,
|
pub struct_value: &'a dyn Struct,
|
||||||
registry: &'a TypeRegistry,
|
pub registry: &'a TypeRegistry,
|
||||||
|
pub processor: Option<&'a P>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StructSerializer<'a> {
|
impl<P: ReflectSerializerProcessor> Serialize for StructSerializer<'_, P> {
|
||||||
pub fn new(struct_value: &'a dyn Struct, registry: &'a TypeRegistry) -> Self {
|
|
||||||
Self {
|
|
||||||
struct_value,
|
|
||||||
registry,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Serialize for StructSerializer<'a> {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
|
@ -63,7 +57,7 @@ impl<'a> Serialize for StructSerializer<'a> {
|
||||||
let key = struct_info.field_at(index).unwrap().name();
|
let key = struct_info.field_at(index).unwrap().name();
|
||||||
state.serialize_field(
|
state.serialize_field(
|
||||||
key,
|
key,
|
||||||
&TypedReflectSerializer::new_internal(value, self.registry),
|
&TypedReflectSerializer::new_internal(value, self.registry, self.processor),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
state.end()
|
state.end()
|
||||||
|
|
|
@ -4,22 +4,16 @@ use crate::{
|
||||||
};
|
};
|
||||||
use serde::{ser::SerializeTupleStruct, Serialize};
|
use serde::{ser::SerializeTupleStruct, Serialize};
|
||||||
|
|
||||||
|
use super::ReflectSerializerProcessor;
|
||||||
|
|
||||||
/// A serializer for [`TupleStruct`] values.
|
/// A serializer for [`TupleStruct`] values.
|
||||||
pub(super) struct TupleStructSerializer<'a> {
|
pub(super) struct TupleStructSerializer<'a, P> {
|
||||||
tuple_struct: &'a dyn TupleStruct,
|
pub tuple_struct: &'a dyn TupleStruct,
|
||||||
registry: &'a TypeRegistry,
|
pub registry: &'a TypeRegistry,
|
||||||
|
pub processor: Option<&'a P>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TupleStructSerializer<'a> {
|
impl<P: ReflectSerializerProcessor> Serialize for TupleStructSerializer<'_, P> {
|
||||||
pub fn new(tuple_struct: &'a dyn TupleStruct, registry: &'a TypeRegistry) -> Self {
|
|
||||||
Self {
|
|
||||||
tuple_struct,
|
|
||||||
registry,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Serialize for TupleStructSerializer<'a> {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
|
@ -53,7 +47,7 @@ impl<'a> Serialize for TupleStructSerializer<'a> {
|
||||||
let field = self.tuple_struct.field(0).unwrap();
|
let field = self.tuple_struct.field(0).unwrap();
|
||||||
return serializer.serialize_newtype_struct(
|
return serializer.serialize_newtype_struct(
|
||||||
tuple_struct_info.type_path_table().ident().unwrap(),
|
tuple_struct_info.type_path_table().ident().unwrap(),
|
||||||
&TypedReflectSerializer::new_internal(field, self.registry),
|
&TypedReflectSerializer::new_internal(field, self.registry, self.processor),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +63,11 @@ impl<'a> Serialize for TupleStructSerializer<'a> {
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
state.serialize_field(&TypedReflectSerializer::new_internal(value, self.registry))?;
|
state.serialize_field(&TypedReflectSerializer::new_internal(
|
||||||
|
value,
|
||||||
|
self.registry,
|
||||||
|
self.processor,
|
||||||
|
))?;
|
||||||
}
|
}
|
||||||
state.end()
|
state.end()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
use crate::{serde::TypedReflectSerializer, Tuple, TypeRegistry};
|
use crate::{serde::TypedReflectSerializer, Tuple, TypeRegistry};
|
||||||
use serde::{ser::SerializeTuple, Serialize};
|
use serde::{ser::SerializeTuple, Serialize};
|
||||||
|
|
||||||
|
use super::ReflectSerializerProcessor;
|
||||||
|
|
||||||
/// A serializer for [`Tuple`] values.
|
/// A serializer for [`Tuple`] values.
|
||||||
pub(super) struct TupleSerializer<'a> {
|
pub(super) struct TupleSerializer<'a, P> {
|
||||||
tuple: &'a dyn Tuple,
|
pub tuple: &'a dyn Tuple,
|
||||||
registry: &'a TypeRegistry,
|
pub registry: &'a TypeRegistry,
|
||||||
|
pub processor: Option<&'a P>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TupleSerializer<'a> {
|
impl<P: ReflectSerializerProcessor> Serialize for TupleSerializer<'_, P> {
|
||||||
pub fn new(tuple: &'a dyn Tuple, registry: &'a TypeRegistry) -> Self {
|
|
||||||
Self { tuple, registry }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Serialize for TupleSerializer<'a> {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
|
@ -21,7 +18,11 @@ impl<'a> Serialize for TupleSerializer<'a> {
|
||||||
let mut state = serializer.serialize_tuple(self.tuple.field_len())?;
|
let mut state = serializer.serialize_tuple(self.tuple.field_len())?;
|
||||||
|
|
||||||
for value in self.tuple.iter_fields() {
|
for value in self.tuple.iter_fields() {
|
||||||
state.serialize_element(&TypedReflectSerializer::new_internal(value, self.registry))?;
|
state.serialize_element(&TypedReflectSerializer::new_internal(
|
||||||
|
value,
|
||||||
|
self.registry,
|
||||||
|
self.processor,
|
||||||
|
))?;
|
||||||
}
|
}
|
||||||
state.end()
|
state.end()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue