Skip to content

Commit db00d9d

Browse files
committed
Fixed FromReflect derive for opaque remote types
1 parent 86cc02d commit db00d9d

File tree

2 files changed

+55
-5
lines changed

2 files changed

+55
-5
lines changed

crates/bevy_reflect/derive/src/from_reflect.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,31 @@ pub(crate) fn impl_opaque(meta: &ReflectMeta) -> proc_macro2::TokenStream {
2727
let bevy_reflect_path = meta.bevy_reflect_path();
2828
let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl();
2929
let where_from_reflect_clause = WhereClauseOptions::new(meta).extend_where_clause(where_clause);
30-
quote! {
31-
impl #impl_generics #bevy_reflect_path::FromReflect for #type_path #ty_generics #where_from_reflect_clause {
32-
fn from_reflect(reflect: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption<Self> {
33-
#FQOption::Some(
30+
31+
let downcast = match meta.remote_ty() {
32+
Some(remote) => {
33+
let remote_ty = remote.type_path();
34+
quote! {
35+
<Self as #bevy_reflect_path::ReflectRemote>::into_wrapper(
3436
#FQClone::clone(
35-
<dyn #bevy_reflect_path::PartialReflect>::try_downcast_ref::<#type_path #ty_generics>(reflect)?
37+
<dyn #bevy_reflect_path::PartialReflect>::try_downcast_ref::<#remote_ty>(reflect)?
3638
)
3739
)
3840
}
3941
}
42+
None => quote! {
43+
#FQClone::clone(
44+
<dyn #bevy_reflect_path::PartialReflect>::try_downcast_ref::<#type_path #ty_generics>(reflect)?
45+
)
46+
},
47+
};
48+
49+
quote! {
50+
impl #impl_generics #bevy_reflect_path::FromReflect for #type_path #ty_generics #where_from_reflect_clause {
51+
fn from_reflect(reflect: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption<Self> {
52+
#FQOption::Some(#downcast)
53+
}
54+
}
4055
}
4156
}
4257

crates/bevy_reflect/src/lib.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3359,6 +3359,41 @@ bevy_reflect::tests::Test {
33593359
);
33603360
}
33613361

3362+
// https://github.com/bevyengine/bevy/issues/19017
3363+
#[test]
3364+
fn should_serialize_opaque_remote_type() {
3365+
mod external_crate {
3366+
use serde::{Deserialize, Serialize};
3367+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
3368+
pub struct Vector2<T>(pub [T; 2]);
3369+
}
3370+
3371+
#[reflect_remote(external_crate::Vector2<i32>)]
3372+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
3373+
#[reflect(Serialize, Deserialize)]
3374+
#[reflect(opaque)]
3375+
struct Vector2Wrapper([i32; 2]);
3376+
3377+
#[derive(Reflect, Debug, PartialEq)]
3378+
struct Point(#[reflect(remote = Vector2Wrapper)] external_crate::Vector2<i32>);
3379+
3380+
let point = Point(external_crate::Vector2([1, 2]));
3381+
3382+
let mut registry = TypeRegistry::new();
3383+
registry.register::<Point>();
3384+
registry.register::<Vector2Wrapper>();
3385+
3386+
let serializer = ReflectSerializer::new(&point, &registry);
3387+
let serialized = ron::to_string(&serializer).unwrap();
3388+
assert_eq!(serialized, r#"{"bevy_reflect::tests::Point":((((1,2))))}"#);
3389+
3390+
let mut deserializer = Deserializer::from_str(&serialized).unwrap();
3391+
let reflect_deserializer = ReflectDeserializer::new(&registry);
3392+
let deserialized = reflect_deserializer.deserialize(&mut deserializer).unwrap();
3393+
let point = <Point as FromReflect>::from_reflect(&*deserialized).unwrap();
3394+
assert_eq!(point, Point(external_crate::Vector2([1, 2])));
3395+
}
3396+
33623397
#[cfg(feature = "glam")]
33633398
mod glam {
33643399
use super::*;

0 commit comments

Comments
 (0)