bevy_reflect_derive/impls/
opaque.rs

1use crate::{
2    impls::{common_partial_reflect_methods, impl_full_reflect, impl_type_path, impl_typed},
3    where_clause_options::WhereClauseOptions,
4    ReflectMeta,
5};
6use bevy_macro_utils::fq_std::{FQClone, FQOption, FQResult};
7use quote::quote;
8
9/// Implements `GetTypeRegistration` and `Reflect` for the given type data.
10pub(crate) fn impl_opaque(meta: &ReflectMeta) -> proc_macro2::TokenStream {
11    let bevy_reflect_path = meta.bevy_reflect_path();
12    let type_path = meta.type_path();
13
14    #[cfg(feature = "documentation")]
15    let with_docs = {
16        let doc = quote::ToTokens::to_token_stream(meta.doc());
17        Some(quote!(.with_docs(#doc)))
18    };
19    #[cfg(not(feature = "documentation"))]
20    let with_docs: Option<proc_macro2::TokenStream> = None;
21
22    let where_clause_options = WhereClauseOptions::new(meta);
23    let typed_impl = impl_typed(
24        &where_clause_options,
25        quote! {
26            let info = #bevy_reflect_path::OpaqueInfo::new::<Self>() #with_docs;
27            #bevy_reflect_path::TypeInfo::Opaque(info)
28        },
29    );
30
31    let type_path_impl = impl_type_path(meta);
32    let full_reflect_impl = impl_full_reflect(&where_clause_options);
33    let common_methods = common_partial_reflect_methods(meta, || None, || None);
34    let clone_fn = meta.attrs().get_clone_impl(bevy_reflect_path);
35
36    let apply_impl = if let Some(remote_ty) = meta.remote_ty() {
37        let ty = remote_ty.type_path();
38        quote! {
39            if let #FQOption::Some(value) = <dyn #bevy_reflect_path::PartialReflect>::try_downcast_ref::<#ty>(value) {
40                *self = Self(#FQClone::clone(value));
41                return #FQResult::Ok(());
42            }
43        }
44    } else {
45        quote! {
46            if let #FQOption::Some(value) = <dyn #bevy_reflect_path::PartialReflect>::try_downcast_ref::<Self>(value) {
47                *self = #FQClone::clone(value);
48                return #FQResult::Ok(());
49            }
50        }
51    };
52
53    #[cfg(not(feature = "functions"))]
54    let function_impls = None::<proc_macro2::TokenStream>;
55    #[cfg(feature = "functions")]
56    let function_impls = crate::impls::impl_function_traits(&where_clause_options);
57
58    #[cfg(not(feature = "auto_register"))]
59    let auto_register = None::<proc_macro2::TokenStream>;
60    #[cfg(feature = "auto_register")]
61    let auto_register = crate::impls::reflect_auto_registration(meta);
62
63    let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl();
64    let where_reflect_clause = where_clause_options.extend_where_clause(where_clause);
65    let get_type_registration_impl = meta.get_type_registration(&where_clause_options);
66
67    quote! {
68        #get_type_registration_impl
69
70        #type_path_impl
71
72        #typed_impl
73
74        #full_reflect_impl
75
76        #function_impls
77
78        #auto_register
79
80        impl #impl_generics #bevy_reflect_path::PartialReflect for #type_path #ty_generics #where_reflect_clause  {
81            #[inline]
82            fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
83                #FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
84            }
85
86            #[inline]
87            fn to_dynamic(&self) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::PartialReflect> {
88                #bevy_reflect_path::__macro_exports::alloc_utils::Box::new(#FQClone::clone(self))
89            }
90
91             #[inline]
92            fn try_apply(
93                &mut self,
94                value: &dyn #bevy_reflect_path::PartialReflect
95            ) -> #FQResult<(), #bevy_reflect_path::ApplyError> {
96                #apply_impl
97
98                #FQResult::Err(
99                    #bevy_reflect_path::ApplyError::MismatchedTypes {
100                        from_type: ::core::convert::Into::into(#bevy_reflect_path::DynamicTypePath::reflect_type_path(value)),
101                        to_type: ::core::convert::Into::into(<Self as #bevy_reflect_path::TypePath>::type_path()),
102                    }
103                )
104            }
105
106            #[inline]
107            fn reflect_kind(&self) -> #bevy_reflect_path::ReflectKind {
108                #bevy_reflect_path::ReflectKind::Opaque
109            }
110
111            #[inline]
112            fn reflect_ref(&self) -> #bevy_reflect_path::ReflectRef {
113                #bevy_reflect_path::ReflectRef::Opaque(self)
114            }
115
116            #[inline]
117            fn reflect_mut(&mut self) -> #bevy_reflect_path::ReflectMut {
118                #bevy_reflect_path::ReflectMut::Opaque(self)
119            }
120
121            #[inline]
122            fn reflect_owned(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::ReflectOwned {
123                #bevy_reflect_path::ReflectOwned::Opaque(self)
124            }
125
126            #common_methods
127
128            #clone_fn
129        }
130    }
131}