@@ -318,15 +318,23 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
318318 Ok ( Box :: new ( dynamic_tuple) )
319319 }
320320 TypeInfo :: Enum ( enum_info) => {
321- let mut dynamic_enum = deserializer. deserialize_enum (
322- enum_info. name ( ) ,
323- enum_info. variant_names ( ) ,
324- EnumVisitor {
321+ let type_name = enum_info. type_name ( ) ;
322+ let mut dynamic_enum = if type_name. starts_with ( "core::option::Option" ) {
323+ deserializer. deserialize_option ( OptionVisitor {
325324 enum_info,
326325 registry : self . registry ,
327- } ,
328- ) ?;
329- dynamic_enum. set_name ( enum_info. type_name ( ) . to_string ( ) ) ;
326+ } ) ?
327+ } else {
328+ deserializer. deserialize_enum (
329+ enum_info. name ( ) ,
330+ enum_info. variant_names ( ) ,
331+ EnumVisitor {
332+ enum_info,
333+ registry : self . registry ,
334+ } ,
335+ ) ?
336+ } ;
337+ dynamic_enum. set_name ( type_name. to_string ( ) ) ;
330338 Ok ( Box :: new ( dynamic_enum) )
331339 }
332340 TypeInfo :: Value ( _) => {
@@ -588,16 +596,7 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> {
588596 ) ?
589597 . into ( ) ,
590598 VariantInfo :: Tuple ( tuple_info) if tuple_info. field_len ( ) == 1 => {
591- let field = tuple_info. field_at ( 0 ) . unwrap ( ) ;
592- let type_info =
593- self . registry
594- . get_type_info ( field. type_id ( ) )
595- . ok_or_else ( || {
596- Error :: custom ( format_args ! (
597- "no registration found for type {}" ,
598- field. type_name( )
599- ) )
600- } ) ?;
599+ let type_info = get_newtype_info ( tuple_info, self . registry ) ?;
601600 let value = variant. newtype_variant_seed ( TypedReflectDeserializer {
602601 type_info,
603602 registry : self . registry ,
@@ -665,6 +664,54 @@ impl<'a, 'de> Visitor<'de> for TupleVariantVisitor<'a> {
665664 }
666665}
667666
667+ struct OptionVisitor < ' a > {
668+ enum_info : & ' static EnumInfo ,
669+ registry : & ' a TypeRegistry ,
670+ }
671+
672+ impl < ' a , ' de > Visitor < ' de > for OptionVisitor < ' a > {
673+ type Value = DynamicEnum ;
674+
675+ fn expecting ( & self , formatter : & mut Formatter ) -> fmt:: Result {
676+ formatter. write_str ( "reflected option value of type " ) ?;
677+ formatter. write_str ( self . enum_info . type_name ( ) )
678+ }
679+
680+ fn visit_some < D > ( self , deserializer : D ) -> Result < Self :: Value , D :: Error >
681+ where
682+ D : serde:: Deserializer < ' de > ,
683+ {
684+ let variant_info = self . enum_info . variant ( "Some" ) . unwrap ( ) ;
685+ match variant_info {
686+ VariantInfo :: Tuple ( tuple_info) if tuple_info. field_len ( ) == 1 => {
687+ let type_info = get_newtype_info ( tuple_info, self . registry ) ?;
688+ let de = TypedReflectDeserializer {
689+ type_info,
690+ registry : self . registry ,
691+ } ;
692+ let mut value = DynamicTuple :: default ( ) ;
693+ value. insert_boxed ( de. deserialize ( deserializer) ?) ;
694+ let mut option = DynamicEnum :: default ( ) ;
695+ option. set_variant ( "Some" , value) ;
696+ Ok ( option)
697+ }
698+ info => Err ( Error :: custom ( format_args ! (
699+ "invalid variant, expected `Some` but got `{}`" ,
700+ info. name( )
701+ ) ) ) ,
702+ }
703+ }
704+
705+ fn visit_none < E > ( self ) -> Result < Self :: Value , E >
706+ where
707+ E : Error ,
708+ {
709+ let mut option = DynamicEnum :: default ( ) ;
710+ option. set_variant ( "None" , ( ) ) ;
711+ Ok ( option)
712+ }
713+ }
714+
668715fn visit_struct < ' de , T , V > (
669716 map : & mut V ,
670717 info : & ' static T ,
@@ -732,6 +779,19 @@ where
732779 Ok ( tuple)
733780}
734781
782+ fn get_newtype_info < E : Error > (
783+ tuple_info : & ' static TupleVariantInfo ,
784+ registry : & TypeRegistry ,
785+ ) -> Result < & ' static TypeInfo , E > {
786+ let field = tuple_info. field_at ( 0 ) . unwrap ( ) ;
787+ registry. get_type_info ( field. type_id ( ) ) . ok_or_else ( || {
788+ Error :: custom ( format_args ! (
789+ "no registration found for type {}" ,
790+ field. type_name( )
791+ ) )
792+ } )
793+ }
794+
735795fn get_type_info < E : de:: Error > (
736796 type_id : TypeId ,
737797 type_name : & str ,
@@ -950,6 +1010,71 @@ mod tests {
9501010 assert_eq ! ( expected, output) ;
9511011 }
9521012
1013+ #[ test]
1014+ fn should_deserialize_option ( ) {
1015+ #[ derive( Reflect , FromReflect , Debug , PartialEq ) ]
1016+ struct OptionTest {
1017+ none : Option < ( ) > ,
1018+ simple : Option < String > ,
1019+ complex : Option < SomeStruct > ,
1020+ }
1021+
1022+ let expected = OptionTest {
1023+ none : None ,
1024+ simple : Some ( String :: from ( "Hello world!" ) ) ,
1025+ complex : Some ( SomeStruct { foo : 123 } ) ,
1026+ } ;
1027+
1028+ let mut registry = get_registry ( ) ;
1029+ registry. register :: < OptionTest > ( ) ;
1030+ registry. register :: < Option < ( ) > > ( ) ;
1031+
1032+ // === Normal === //
1033+ let input = r#"{
1034+ "bevy_reflect::serde::de::tests::should_deserialize_option::OptionTest": (
1035+ none: None,
1036+ simple: Some("Hello world!"),
1037+ complex: Some((
1038+ foo: 123,
1039+ )),
1040+ ),
1041+ }"# ;
1042+
1043+ let reflect_deserializer = UntypedReflectDeserializer :: new ( & registry) ;
1044+ let mut ron_deserializer = ron:: de:: Deserializer :: from_str ( input) . unwrap ( ) ;
1045+ let dynamic_output = reflect_deserializer
1046+ . deserialize ( & mut ron_deserializer)
1047+ . unwrap ( ) ;
1048+
1049+ let output = <OptionTest as FromReflect >:: from_reflect ( dynamic_output. as_ref ( ) ) . unwrap ( ) ;
1050+ assert_eq ! ( expected, output, "failed to deserialize Options" ) ;
1051+
1052+ // === Implicit Some === //
1053+ let input = r#"
1054+ #![enable(implicit_some)]
1055+ {
1056+ "bevy_reflect::serde::de::tests::should_deserialize_option::OptionTest": (
1057+ none: None,
1058+ simple: "Hello world!",
1059+ complex: (
1060+ foo: 123,
1061+ ),
1062+ ),
1063+ }"# ;
1064+
1065+ let reflect_deserializer = UntypedReflectDeserializer :: new ( & registry) ;
1066+ let mut ron_deserializer = ron:: de:: Deserializer :: from_str ( input) . unwrap ( ) ;
1067+ let dynamic_output = reflect_deserializer
1068+ . deserialize ( & mut ron_deserializer)
1069+ . unwrap ( ) ;
1070+
1071+ let output = <OptionTest as FromReflect >:: from_reflect ( dynamic_output. as_ref ( ) ) . unwrap ( ) ;
1072+ assert_eq ! (
1073+ expected, output,
1074+ "failed to deserialize Options with implicit Some"
1075+ ) ;
1076+ }
1077+
9531078 #[ test]
9541079 fn enum_should_deserialize ( ) {
9551080 #[ derive( Reflect ) ]
0 commit comments