pub use serializable::*; pub use serialize_with_registry::*; pub use serializer::*; mod arrays; mod custom_serialization; mod enums; mod error_utils; mod lists; mod maps; mod serializable; mod serialize_with_registry; mod serializer; mod sets; mod structs; mod tuple_structs; mod tuples; #[cfg(test)] mod tests { use crate::{ self as bevy_reflect, serde::ReflectSerializer, PartialReflect, Reflect, ReflectSerialize, Struct, TypeRegistry, }; use bevy_utils::{HashMap, HashSet}; use core::{f32::consts::PI, ops::RangeInclusive}; use ron::{extensions::Extensions, ser::PrettyConfig}; use serde::Serialize; #[derive(Reflect, Debug, PartialEq)] struct MyStruct { primitive_value: i8, option_value: Option, option_value_complex: Option, tuple_value: (f32, usize), list_value: Vec, array_value: [i32; 5], map_value: HashMap, set_value: HashSet, struct_value: SomeStruct, tuple_struct_value: SomeTupleStruct, unit_struct: SomeUnitStruct, unit_enum: SomeEnum, newtype_enum: SomeEnum, tuple_enum: SomeEnum, struct_enum: SomeEnum, ignored_struct: SomeIgnoredStruct, ignored_tuple_struct: SomeIgnoredTupleStruct, ignored_struct_variant: SomeIgnoredEnum, ignored_tuple_variant: SomeIgnoredEnum, custom_serialize: CustomSerialize, } #[derive(Reflect, Debug, PartialEq)] struct SomeStruct { foo: i64, } #[derive(Reflect, Debug, PartialEq)] struct SomeTupleStruct(String); #[derive(Reflect, Debug, PartialEq)] struct SomeUnitStruct; #[derive(Reflect, Debug, PartialEq)] struct SomeIgnoredStruct { #[reflect(ignore)] ignored: i32, } #[derive(Reflect, Debug, PartialEq)] struct SomeIgnoredTupleStruct(#[reflect(ignore)] i32); #[derive(Reflect, Debug, PartialEq)] enum SomeEnum { Unit, NewType(usize), Tuple(f32, f32), Struct { foo: String }, } #[derive(Reflect, Debug, PartialEq)] enum SomeIgnoredEnum { Tuple(#[reflect(ignore)] f32, #[reflect(ignore)] f32), Struct { #[reflect(ignore)] foo: String, }, } #[derive(Reflect, Debug, PartialEq, Serialize)] struct SomeSerializableStruct { foo: i64, } /// Implements a custom serialize using `#[reflect(Serialize)]`. /// /// For testing purposes, this just uses the generated one from deriving Serialize. #[derive(Reflect, Debug, PartialEq, Serialize)] #[reflect(Serialize)] struct CustomSerialize { value: usize, #[serde(rename = "renamed")] inner_struct: SomeSerializableStruct, } fn get_registry() -> TypeRegistry { let mut registry = TypeRegistry::default(); registry.register::(); registry.register::(); registry.register::(); registry.register::(); registry.register::(); registry.register::(); registry.register::(); registry.register::(); registry.register::(); registry.register::(); registry.register_type_data::(); registry.register::(); registry.register::>(); registry.register_type_data::, ReflectSerialize>(); registry } fn get_my_struct() -> MyStruct { let mut map = HashMap::new(); map.insert(64, 32); let mut set = HashSet::new(); set.insert(64); MyStruct { primitive_value: 123, option_value: Some(String::from("Hello world!")), option_value_complex: Some(SomeStruct { foo: 123 }), tuple_value: (PI, 1337), list_value: vec![-2, -1, 0, 1, 2], array_value: [-2, -1, 0, 1, 2], map_value: map, set_value: set, struct_value: SomeStruct { foo: 999999999 }, tuple_struct_value: SomeTupleStruct(String::from("Tuple Struct")), unit_struct: SomeUnitStruct, unit_enum: SomeEnum::Unit, newtype_enum: SomeEnum::NewType(123), tuple_enum: SomeEnum::Tuple(1.23, 3.21), struct_enum: SomeEnum::Struct { foo: String::from("Struct variant value"), }, ignored_struct: SomeIgnoredStruct { ignored: 123 }, ignored_tuple_struct: SomeIgnoredTupleStruct(123), ignored_struct_variant: SomeIgnoredEnum::Struct { foo: String::from("Struct Variant"), }, ignored_tuple_variant: SomeIgnoredEnum::Tuple(1.23, 3.45), custom_serialize: CustomSerialize { value: 100, inner_struct: SomeSerializableStruct { foo: 101 }, }, } } #[test] fn should_serialize() { let input = get_my_struct(); let registry = get_registry(); let serializer = ReflectSerializer::new(&input, ®istry); let config = PrettyConfig::default() .new_line(String::from("\n")) .indentor(String::from(" ")); let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"{ "bevy_reflect::serde::ser::tests::MyStruct": ( primitive_value: 123, option_value: Some("Hello world!"), option_value_complex: Some(( foo: 123, )), tuple_value: (3.1415927, 1337), list_value: [ -2, -1, 0, 1, 2, ], array_value: (-2, -1, 0, 1, 2), map_value: { 64: 32, }, set_value: [ 64, ], struct_value: ( foo: 999999999, ), tuple_struct_value: ("Tuple Struct"), unit_struct: (), unit_enum: Unit, newtype_enum: NewType(123), tuple_enum: Tuple(1.23, 3.21), struct_enum: Struct( foo: "Struct variant value", ), ignored_struct: (), ignored_tuple_struct: (), ignored_struct_variant: Struct(), ignored_tuple_variant: Tuple(), custom_serialize: ( value: 100, renamed: ( foo: 101, ), ), ), }"#; assert_eq!(expected, output); } #[test] fn should_serialize_option() { #[derive(Reflect, Debug, PartialEq)] struct OptionTest { none: Option<()>, simple: Option, complex: Option, } let value = OptionTest { none: None, simple: Some(String::from("Hello world!")), complex: Some(SomeStruct { foo: 123 }), }; let registry = get_registry(); let serializer = ReflectSerializer::new(&value, ®istry); // === Normal === // let config = PrettyConfig::default() .new_line(String::from("\n")) .indentor(String::from(" ")); let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"{ "bevy_reflect::serde::ser::tests::OptionTest": ( none: None, simple: Some("Hello world!"), complex: Some(( foo: 123, )), ), }"#; assert_eq!(expected, output); // === Implicit Some === // let config = PrettyConfig::default() .new_line(String::from("\n")) .extensions(Extensions::IMPLICIT_SOME) .indentor(String::from(" ")); let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"#![enable(implicit_some)] { "bevy_reflect::serde::ser::tests::OptionTest": ( none: None, simple: "Hello world!", complex: ( foo: 123, ), ), }"#; assert_eq!(expected, output); } #[test] fn enum_should_serialize() { #[derive(Reflect)] enum MyEnum { Unit, NewType(usize), Tuple(f32, f32), Struct { value: String }, } let mut registry = get_registry(); registry.register::(); let config = PrettyConfig::default().new_line(String::from("\n")); // === Unit Variant === // let value = MyEnum::Unit; let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ "bevy_reflect::serde::ser::tests::MyEnum": Unit, }"#; assert_eq!(expected, output); // === NewType Variant === // let value = MyEnum::NewType(123); let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ "bevy_reflect::serde::ser::tests::MyEnum": NewType(123), }"#; assert_eq!(expected, output); // === Tuple Variant === // let value = MyEnum::Tuple(1.23, 3.21); let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ "bevy_reflect::serde::ser::tests::MyEnum": Tuple(1.23, 3.21), }"#; assert_eq!(expected, output); // === Struct Variant === // let value = MyEnum::Struct { value: String::from("I <3 Enums"), }; let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"{ "bevy_reflect::serde::ser::tests::MyEnum": Struct( value: "I <3 Enums", ), }"#; assert_eq!(expected, output); } #[test] fn should_serialize_non_self_describing_binary() { let input = get_my_struct(); let registry = get_registry(); let serializer = ReflectSerializer::new(&input, ®istry); let bytes = bincode::serialize(&serializer).unwrap(); let expected: Vec = vec![ 1, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 98, 101, 118, 121, 95, 114, 101, 102, 108, 101, 99, 116, 58, 58, 115, 101, 114, 100, 101, 58, 58, 115, 101, 114, 58, 58, 116, 101, 115, 116, 115, 58, 58, 77, 121, 83, 116, 114, 117, 99, 116, 123, 1, 12, 0, 0, 0, 0, 0, 0, 0, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33, 1, 123, 0, 0, 0, 0, 0, 0, 0, 219, 15, 73, 64, 57, 5, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 64, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 64, 255, 201, 154, 59, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 84, 117, 112, 108, 101, 32, 83, 116, 114, 117, 99, 116, 0, 0, 0, 0, 1, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 164, 112, 157, 63, 164, 112, 77, 64, 3, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 83, 116, 114, 117, 99, 116, 32, 118, 97, 114, 105, 97, 110, 116, 32, 118, 97, 108, 117, 101, 1, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, ]; assert_eq!(expected, bytes); } #[test] fn should_serialize_self_describing_binary() { let input = get_my_struct(); let registry = get_registry(); let serializer = ReflectSerializer::new(&input, ®istry); let bytes: Vec = rmp_serde::to_vec(&serializer).unwrap(); let expected: Vec = vec![ 129, 217, 41, 98, 101, 118, 121, 95, 114, 101, 102, 108, 101, 99, 116, 58, 58, 115, 101, 114, 100, 101, 58, 58, 115, 101, 114, 58, 58, 116, 101, 115, 116, 115, 58, 58, 77, 121, 83, 116, 114, 117, 99, 116, 220, 0, 20, 123, 172, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33, 145, 123, 146, 202, 64, 73, 15, 219, 205, 5, 57, 149, 254, 255, 0, 1, 2, 149, 254, 255, 0, 1, 2, 129, 64, 32, 145, 64, 145, 206, 59, 154, 201, 255, 172, 84, 117, 112, 108, 101, 32, 83, 116, 114, 117, 99, 116, 144, 164, 85, 110, 105, 116, 129, 167, 78, 101, 119, 84, 121, 112, 101, 123, 129, 165, 84, 117, 112, 108, 101, 146, 202, 63, 157, 112, 164, 202, 64, 77, 112, 164, 129, 166, 83, 116, 114, 117, 99, 116, 145, 180, 83, 116, 114, 117, 99, 116, 32, 118, 97, 114, 105, 97, 110, 116, 32, 118, 97, 108, 117, 101, 144, 144, 129, 166, 83, 116, 114, 117, 99, 116, 144, 129, 165, 84, 117, 112, 108, 101, 144, 146, 100, 145, 101, ]; assert_eq!(expected, bytes); } #[test] fn should_serialize_dynamic_option() { #[derive(Default, Reflect)] struct OtherStruct { some: Option, none: Option, } let value = OtherStruct { some: Some(SomeStruct { foo: 999999999 }), none: None, }; let dynamic = value.clone_dynamic(); let reflect = dynamic.as_partial_reflect(); let registry = get_registry(); let serializer = ReflectSerializer::new(reflect, ®istry); let mut buf = Vec::new(); let format = serde_json::ser::PrettyFormatter::with_indent(b" "); let mut ser = serde_json::Serializer::with_formatter(&mut buf, format); serializer.serialize(&mut ser).unwrap(); let output = core::str::from_utf8(&buf).unwrap(); let expected = r#"{ "bevy_reflect::serde::ser::tests::OtherStruct": { "some": { "foo": 999999999 }, "none": null } }"#; assert_eq!(expected, output); } #[test] fn should_return_error_if_missing_registration() { let value = RangeInclusive::::new(0.0, 1.0); let registry = TypeRegistry::new(); let serializer = ReflectSerializer::new(&value, ®istry); let error = ron::ser::to_string(&serializer).unwrap_err(); #[cfg(feature = "debug_stack")] assert_eq!( error, ron::Error::Message( "type `core::ops::RangeInclusive` is not registered in the type registry (stack: `core::ops::RangeInclusive`)" .to_string(), ) ); #[cfg(not(feature = "debug_stack"))] assert_eq!( error, ron::Error::Message( "type `core::ops::RangeInclusive` is not registered in the type registry" .to_string(), ) ); } #[test] fn should_return_error_if_missing_type_data() { let value = RangeInclusive::::new(0.0, 1.0); let mut registry = TypeRegistry::new(); registry.register::>(); let serializer = ReflectSerializer::new(&value, ®istry); let error = ron::ser::to_string(&serializer).unwrap_err(); #[cfg(feature = "debug_stack")] assert_eq!( error, ron::Error::Message( "type `core::ops::RangeInclusive` did not register the `ReflectSerialize` or `ReflectSerializeWithRegistry` type data. For certain types, this may need to be registered manually using `register_type_data` (stack: `core::ops::RangeInclusive`)".to_string() ) ); #[cfg(not(feature = "debug_stack"))] assert_eq!( error, ron::Error::Message( "type `core::ops::RangeInclusive` did not register the `ReflectSerialize` type data. For certain types, this may need to be registered manually using `register_type_data`".to_string() ) ); } #[cfg(feature = "functions")] mod functions { use super::*; use crate::func::{DynamicFunction, IntoFunction}; #[test] fn should_not_serialize_function() { #[derive(Reflect)] #[reflect(from_reflect = false)] struct MyStruct { func: DynamicFunction<'static>, } let value: Box = Box::new(MyStruct { func: String::new.into_function(), }); let registry = TypeRegistry::new(); let serializer = ReflectSerializer::new(value.as_partial_reflect(), ®istry); let error = ron::ser::to_string(&serializer).unwrap_err(); #[cfg(feature = "debug_stack")] assert_eq!( error, ron::Error::Message("functions cannot be serialized (stack: `bevy_reflect::serde::ser::tests::functions::MyStruct`)".to_string()) ); #[cfg(not(feature = "debug_stack"))] assert_eq!( error, ron::Error::Message("functions cannot be serialized".to_string()) ); } } #[cfg(feature = "debug_stack")] mod debug_stack { use super::*; #[test] fn should_report_context_in_errors() { #[derive(Reflect)] struct Foo { bar: Bar, } #[derive(Reflect)] struct Bar { some_other_field: Option, baz: Baz, } #[derive(Reflect)] struct Baz { value: Vec>, } let value = Foo { bar: Bar { some_other_field: Some(123), baz: Baz { value: vec![0.0..=1.0], }, }, }; let registry = TypeRegistry::new(); let serializer = ReflectSerializer::new(&value, ®istry); let error = ron::ser::to_string(&serializer).unwrap_err(); assert_eq!( error, ron::Error::Message( "type `core::ops::RangeInclusive` is not registered in the type registry (stack: `bevy_reflect::serde::ser::tests::debug_stack::Foo` -> `bevy_reflect::serde::ser::tests::debug_stack::Bar` -> `bevy_reflect::serde::ser::tests::debug_stack::Baz` -> `alloc::vec::Vec>` -> `core::ops::RangeInclusive`)".to_string() ) ); } } }