reflect: TypePath part 2 (#8768)
				
					
				
			# Objective
- Followup to #7184.
- ~Deprecate `TypeUuid` and remove its internal references.~ No longer
part of this PR.
- Use `TypePath` for the type registry, and (de)serialisation instead of
`std::any::type_name`.
- Allow accessing type path information behind proxies.
## Solution
- Introduce methods on `TypeInfo` and friends for dynamically querying
type path. These methods supersede the old `type_name` methods.
- Remove `Reflect::type_name` in favor of `DynamicTypePath::type_path`
and `TypeInfo::type_path_table`.
- Switch all uses of `std::any::type_name` in reflection, non-debugging
contexts to use `TypePath`.
---
## Changelog
- Added `TypePathTable` for dynamically accessing methods on `TypePath`
through `TypeInfo` and the type registry.
- Removed `type_name` from all `TypeInfo`-like structs.
- Added `type_path` and `type_path_table` methods to all `TypeInfo`-like
structs.
- Removed `Reflect::type_name` in favor of
`DynamicTypePath::reflect_type_path` and `TypeInfo::type_path`.
- Changed the signature of all `DynamicTypePath` methods to return
strings with a static lifetime.
## Migration Guide
- Rely on `TypePath` instead of `std::any::type_name` for all stability
guarantees and for use in all reflection contexts, this is used through
with one of the following APIs:
  - `TypePath::type_path` if you have a concrete type and not a value.
- `DynamicTypePath::reflect_type_path` if you have an `dyn Reflect`
value without a concrete type.
- `TypeInfo::type_path` for use through the registry or if you want to
work with the represented type of a `DynamicFoo`.
  
- Remove `type_name` from manual `Reflect` implementations.
- Use `type_path` and `type_path_table` in place of `type_name` on
`TypeInfo`-like structs.
- Use `get_with_type_path(_mut)` over `get_with_type_name(_mut)`.
## Note to reviewers
I think if anything we were a little overzealous in merging #7184 and we
should take that extra care here.
In my mind, this is the "point of no return" for `TypePath` and while I
think we all agree on the design, we should carefully consider if the
finer details and current implementations are actually how we want them
moving forward.
For example [this incorrect `TypePath` implementation for
`String`](3fea3c6c0b/crates/bevy_reflect/src/impls/std.rs (L90))
(note that `String` is in the default Rust prelude) snuck in completely
under the radar.
			
			
This commit is contained in:
		
							parent
							
								
									92294de08d
								
							
						
					
					
						commit
						262846e702
					
				@ -728,7 +728,7 @@ impl App {
 | 
			
		||||
    /// See [`bevy_reflect::TypeRegistry::register_type_data`].
 | 
			
		||||
    #[cfg(feature = "bevy_reflect")]
 | 
			
		||||
    pub fn register_type_data<
 | 
			
		||||
        T: bevy_reflect::Reflect + 'static,
 | 
			
		||||
        T: bevy_reflect::Reflect + bevy_reflect::TypePath,
 | 
			
		||||
        D: bevy_reflect::TypeData + bevy_reflect::FromType<T>,
 | 
			
		||||
    >(
 | 
			
		||||
        &mut self,
 | 
			
		||||
 | 
			
		||||
@ -146,7 +146,8 @@ impl<B: Bundle + Reflect + FromWorld> FromType<B> for ReflectBundle {
 | 
			
		||||
                        .for_each(|field| insert_field::<B>(entity, field, registry)),
 | 
			
		||||
                    _ => panic!(
 | 
			
		||||
                        "expected bundle `{}` to be named struct or tuple",
 | 
			
		||||
                        std::any::type_name::<B>()
 | 
			
		||||
                        // FIXME: once we have unique reflect, use `TypePath`.
 | 
			
		||||
                        std::any::type_name::<B>(),
 | 
			
		||||
                    ),
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
@ -163,7 +164,8 @@ impl<B: Bundle + Reflect + FromWorld> FromType<B> for ReflectBundle {
 | 
			
		||||
                        .for_each(|field| apply_or_insert_field::<B>(entity, field, registry)),
 | 
			
		||||
                    _ => panic!(
 | 
			
		||||
                        "expected bundle `{}` to be named struct or tuple",
 | 
			
		||||
                        std::any::type_name::<B>()
 | 
			
		||||
                        // FIXME: once we have unique reflect, use `TypePath`.
 | 
			
		||||
                        std::any::type_name::<B>(),
 | 
			
		||||
                    ),
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
@ -188,14 +190,14 @@ fn insert_field<B: 'static>(
 | 
			
		||||
            if world.components().get_id(TypeId::of::<B>()).is_some() {
 | 
			
		||||
                panic!(
 | 
			
		||||
                    "no `ReflectComponent` registration found for `{}`",
 | 
			
		||||
                    field.type_name()
 | 
			
		||||
                    field.reflect_type_path(),
 | 
			
		||||
                );
 | 
			
		||||
            };
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        panic!(
 | 
			
		||||
            "no `ReflectBundle` registration found for `{}`",
 | 
			
		||||
            field.type_name()
 | 
			
		||||
            field.reflect_type_path(),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -214,14 +216,14 @@ fn apply_or_insert_field<B: 'static>(
 | 
			
		||||
            if world.components().get_id(TypeId::of::<B>()).is_some() {
 | 
			
		||||
                panic!(
 | 
			
		||||
                    "no `ReflectComponent` registration found for `{}`",
 | 
			
		||||
                    field.type_name()
 | 
			
		||||
                    field.reflect_type_path(),
 | 
			
		||||
                );
 | 
			
		||||
            };
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        panic!(
 | 
			
		||||
            "no `ReflectBundle` registration found for `{}`",
 | 
			
		||||
            field.type_name()
 | 
			
		||||
            field.reflect_type_path(),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -161,10 +161,10 @@ impl<'w, 's, 'a> ReflectCommandExt for EntityCommands<'w, 's, 'a> {
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn remove_reflect(&mut self, component_type_name: impl Into<Cow<'static, str>>) -> &mut Self {
 | 
			
		||||
    fn remove_reflect(&mut self, component_type_path: impl Into<Cow<'static, str>>) -> &mut Self {
 | 
			
		||||
        self.commands.add(RemoveReflect {
 | 
			
		||||
            entity: self.entity,
 | 
			
		||||
            component_type_name: component_type_name.into(),
 | 
			
		||||
            component_type_path: component_type_path.into(),
 | 
			
		||||
        });
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
@ -189,15 +189,15 @@ fn insert_reflect(
 | 
			
		||||
    type_registry: &TypeRegistry,
 | 
			
		||||
    component: Box<dyn Reflect>,
 | 
			
		||||
) {
 | 
			
		||||
    let type_info = component.type_name();
 | 
			
		||||
    let type_info = component.reflect_type_path();
 | 
			
		||||
    let Some(mut entity) = world.get_entity_mut(entity) else {
 | 
			
		||||
        panic!("error[B0003]: Could not insert a reflected component (of type {}) for entity {entity:?} because it doesn't exist in this World.", component.type_name());
 | 
			
		||||
        panic!("error[B0003]: Could not insert a reflected component (of type {}) for entity {entity:?} because it doesn't exist in this World.", component.reflect_type_path());
 | 
			
		||||
    };
 | 
			
		||||
    let Some(type_registration) = type_registry.get_with_name(type_info) else {
 | 
			
		||||
        panic!("Could not get type registration (for component type {}) because it doesn't exist in the TypeRegistry.", component.type_name());
 | 
			
		||||
    let Some(type_registration) = type_registry.get_with_type_path(type_info) else {
 | 
			
		||||
        panic!("Could not get type registration (for component type {}) because it doesn't exist in the TypeRegistry.", component.reflect_type_path());
 | 
			
		||||
    };
 | 
			
		||||
    let Some(reflect_component) = type_registration.data::<ReflectComponent>() else {
 | 
			
		||||
        panic!("Could not get ReflectComponent data (for component type {}) because it doesn't exist in this TypeRegistration.", component.type_name());
 | 
			
		||||
        panic!("Could not get ReflectComponent data (for component type {}) because it doesn't exist in this TypeRegistration.", component.reflect_type_path());
 | 
			
		||||
    };
 | 
			
		||||
    reflect_component.insert(&mut entity, &*component);
 | 
			
		||||
}
 | 
			
		||||
@ -246,12 +246,12 @@ fn remove_reflect(
 | 
			
		||||
    world: &mut World,
 | 
			
		||||
    entity: Entity,
 | 
			
		||||
    type_registry: &TypeRegistry,
 | 
			
		||||
    component_type_name: Cow<'static, str>,
 | 
			
		||||
    component_type_path: Cow<'static, str>,
 | 
			
		||||
) {
 | 
			
		||||
    let Some(mut entity) = world.get_entity_mut(entity) else {
 | 
			
		||||
        return;
 | 
			
		||||
    };
 | 
			
		||||
    let Some(type_registration) = type_registry.get_with_name(&component_type_name) else {
 | 
			
		||||
    let Some(type_registration) = type_registry.get_with_type_path(&component_type_path) else {
 | 
			
		||||
        return;
 | 
			
		||||
    };
 | 
			
		||||
    let Some(reflect_component) = type_registration.data::<ReflectComponent>() else {
 | 
			
		||||
@ -269,7 +269,7 @@ pub struct RemoveReflect {
 | 
			
		||||
    pub entity: Entity,
 | 
			
		||||
    /// The [`Component`](crate::component::Component) type name that will be used to remove a component
 | 
			
		||||
    /// of the same type from the entity.
 | 
			
		||||
    pub component_type_name: Cow<'static, str>,
 | 
			
		||||
    pub component_type_path: Cow<'static, str>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Command for RemoveReflect {
 | 
			
		||||
@ -279,7 +279,7 @@ impl Command for RemoveReflect {
 | 
			
		||||
            world,
 | 
			
		||||
            self.entity,
 | 
			
		||||
            ®istry.read(),
 | 
			
		||||
            self.component_type_name,
 | 
			
		||||
            self.component_type_path,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -413,7 +413,7 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
        commands
 | 
			
		||||
            .entity(entity)
 | 
			
		||||
            .remove_reflect(boxed_reflect_component_a.type_name().to_owned());
 | 
			
		||||
            .remove_reflect(boxed_reflect_component_a.reflect_type_path().to_owned());
 | 
			
		||||
        system_state.apply(&mut world);
 | 
			
		||||
 | 
			
		||||
        assert_eq!(world.entity(entity).get::<ComponentA>(), None);
 | 
			
		||||
@ -443,7 +443,7 @@ mod tests {
 | 
			
		||||
        commands
 | 
			
		||||
            .entity(entity)
 | 
			
		||||
            .remove_reflect_with_registry::<TypeRegistryResource>(
 | 
			
		||||
                boxed_reflect_component_a.type_name().to_owned(),
 | 
			
		||||
                boxed_reflect_component_a.reflect_type_path().to_owned(),
 | 
			
		||||
            );
 | 
			
		||||
        system_state.apply(&mut world);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -34,14 +34,14 @@ pub(crate) enum ReflectDerive<'a> {
 | 
			
		||||
/// //                          traits
 | 
			
		||||
/// //        |----------------------------------------|
 | 
			
		||||
/// #[reflect(PartialEq, Serialize, Deserialize, Default)]
 | 
			
		||||
/// //            type_name       generics
 | 
			
		||||
/// //            type_path       generics
 | 
			
		||||
/// //     |-------------------||----------|
 | 
			
		||||
/// struct ThingThatImReflecting<T1, T2, T3> {/* ... */}
 | 
			
		||||
/// ```
 | 
			
		||||
pub(crate) struct ReflectMeta<'a> {
 | 
			
		||||
    /// The registered traits for this type.
 | 
			
		||||
    traits: ReflectTraits,
 | 
			
		||||
    /// The name of this type.
 | 
			
		||||
    /// The path to this type.
 | 
			
		||||
    type_path: ReflectTypePath<'a>,
 | 
			
		||||
    /// A cached instance of the path to the `bevy_reflect` crate.
 | 
			
		||||
    bevy_reflect_path: Path,
 | 
			
		||||
@ -389,7 +389,7 @@ impl<'a> ReflectMeta<'a> {
 | 
			
		||||
        self.traits.from_reflect_attrs()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The name of this struct.
 | 
			
		||||
    /// The path to this type.
 | 
			
		||||
    pub fn type_path(&self) -> &ReflectTypePath<'a> {
 | 
			
		||||
        &self.type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -73,7 +73,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
 | 
			
		||||
                if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #bevy_reflect_path::Reflect::reflect_ref(#ref_value) {
 | 
			
		||||
                    match #bevy_reflect_path::Enum::variant_name(#ref_value) {
 | 
			
		||||
                        #(#variant_names => #fqoption::Some(#variant_constructors),)*
 | 
			
		||||
                        name => panic!("variant with name `{}` does not exist on enum `{}`", name, ::core::any::type_name::<Self>()),
 | 
			
		||||
                        name => panic!("variant with name `{}` does not exist on enum `{}`", name, <Self as #bevy_reflect_path::TypePath>::type_path()),
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    #FQOption::None
 | 
			
		||||
 | 
			
		||||
@ -58,20 +58,18 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    let string_name = enum_path.get_ident().unwrap().to_string();
 | 
			
		||||
 | 
			
		||||
    #[cfg(feature = "documentation")]
 | 
			
		||||
    let info_generator = {
 | 
			
		||||
        let doc = reflect_enum.meta().doc();
 | 
			
		||||
        quote! {
 | 
			
		||||
            #bevy_reflect_path::EnumInfo::new::<Self>(#string_name, &variants).with_docs(#doc)
 | 
			
		||||
            #bevy_reflect_path::EnumInfo::new::<Self>(&variants).with_docs(#doc)
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    #[cfg(not(feature = "documentation"))]
 | 
			
		||||
    let info_generator = {
 | 
			
		||||
        quote! {
 | 
			
		||||
            #bevy_reflect_path::EnumInfo::new::<Self>(#string_name, &variants)
 | 
			
		||||
            #bevy_reflect_path::EnumInfo::new::<Self>(&variants)
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -188,11 +186,6 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        impl #impl_generics #bevy_reflect_path::Reflect for #enum_path #ty_generics #where_reflect_clause {
 | 
			
		||||
            #[inline]
 | 
			
		||||
            fn type_name(&self) -> &str {
 | 
			
		||||
                ::core::any::type_name::<Self>()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
 | 
			
		||||
                #FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
 | 
			
		||||
@ -264,11 +257,11 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
 | 
			
		||||
                            #(#variant_names => {
 | 
			
		||||
                                *self = #variant_constructors
 | 
			
		||||
                            })*
 | 
			
		||||
                            name => panic!("variant with name `{}` does not exist on enum `{}`", name, ::core::any::type_name::<Self>()),
 | 
			
		||||
                            name => panic!("variant with name `{}` does not exist on enum `{}`", name, <Self as #bevy_reflect_path::TypePath>::type_path()),
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    panic!("`{}` is not an enum", #bevy_reflect_path::Reflect::type_name(#ref_value));
 | 
			
		||||
                    panic!("`{}` is not an enum", #bevy_reflect_path::DynamicTypePath::reflect_type_path(#ref_value));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -63,20 +63,18 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let string_name = struct_path.get_ident().unwrap().to_string();
 | 
			
		||||
 | 
			
		||||
    #[cfg(feature = "documentation")]
 | 
			
		||||
    let info_generator = {
 | 
			
		||||
        let doc = reflect_struct.meta().doc();
 | 
			
		||||
        quote! {
 | 
			
		||||
            #bevy_reflect_path::StructInfo::new::<Self>(#string_name, &fields).with_docs(#doc)
 | 
			
		||||
            #bevy_reflect_path::StructInfo::new::<Self>(&fields).with_docs(#doc)
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    #[cfg(not(feature = "documentation"))]
 | 
			
		||||
    let info_generator = {
 | 
			
		||||
        quote! {
 | 
			
		||||
            #bevy_reflect_path::StructInfo::new::<Self>(#string_name, &fields)
 | 
			
		||||
            #bevy_reflect_path::StructInfo::new::<Self>(&fields)
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -163,11 +161,6 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        impl #impl_generics #bevy_reflect_path::Reflect for #struct_path #ty_generics #where_reflect_clause {
 | 
			
		||||
            #[inline]
 | 
			
		||||
            fn type_name(&self) -> &str {
 | 
			
		||||
                ::core::any::type_name::<Self>()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
 | 
			
		||||
                #FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
 | 
			
		||||
 | 
			
		||||
@ -57,20 +57,18 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2::
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let string_name = struct_path.get_ident().unwrap().to_string();
 | 
			
		||||
 | 
			
		||||
    #[cfg(feature = "documentation")]
 | 
			
		||||
    let info_generator = {
 | 
			
		||||
        let doc = reflect_struct.meta().doc();
 | 
			
		||||
        quote! {
 | 
			
		||||
           #bevy_reflect_path::TupleStructInfo::new::<Self>(#string_name, &fields).with_docs(#doc)
 | 
			
		||||
           #bevy_reflect_path::TupleStructInfo::new::<Self>(&fields).with_docs(#doc)
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    #[cfg(not(feature = "documentation"))]
 | 
			
		||||
    let info_generator = {
 | 
			
		||||
        quote! {
 | 
			
		||||
            #bevy_reflect_path::TupleStructInfo::new::<Self>(#string_name, &fields)
 | 
			
		||||
            #bevy_reflect_path::TupleStructInfo::new::<Self>(&fields)
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -133,11 +131,6 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2::
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        impl #impl_generics #bevy_reflect_path::Reflect for #struct_path #ty_generics #where_reflect_clause {
 | 
			
		||||
            #[inline]
 | 
			
		||||
            fn type_name(&self) -> &str {
 | 
			
		||||
                ::core::any::type_name::<Self>()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
 | 
			
		||||
                #FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
 | 
			
		||||
 | 
			
		||||
@ -45,11 +45,6 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream {
 | 
			
		||||
        #typed_impl
 | 
			
		||||
 | 
			
		||||
        impl #impl_generics #bevy_reflect_path::Reflect for #type_path #ty_generics #where_reflect_clause  {
 | 
			
		||||
            #[inline]
 | 
			
		||||
            fn type_name(&self) -> &str {
 | 
			
		||||
                ::core::any::type_name::<Self>()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
 | 
			
		||||
                #FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
 | 
			
		||||
@ -96,7 +91,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream {
 | 
			
		||||
                if let #FQOption::Some(value) = <dyn #FQAny>::downcast_ref::<Self>(value) {
 | 
			
		||||
                    *self = #FQClone::clone(value);
 | 
			
		||||
                } else {
 | 
			
		||||
                    panic!("Value is not {}.", ::core::any::type_name::<Self>());
 | 
			
		||||
                    panic!("Value is not {}.", <Self as #bevy_reflect_path::TypePath>::type_path());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
use crate::{
 | 
			
		||||
    self as bevy_reflect, utility::reflect_hasher, Reflect, ReflectMut, ReflectOwned, ReflectRef,
 | 
			
		||||
    TypeInfo,
 | 
			
		||||
    TypeInfo, TypePath, TypePathTable,
 | 
			
		||||
};
 | 
			
		||||
use bevy_reflect_derive::impl_type_path;
 | 
			
		||||
use std::{
 | 
			
		||||
@ -77,9 +77,9 @@ pub trait Array: Reflect {
 | 
			
		||||
/// A container for compile-time array info.
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct ArrayInfo {
 | 
			
		||||
    type_name: &'static str,
 | 
			
		||||
    type_path: TypePathTable,
 | 
			
		||||
    type_id: TypeId,
 | 
			
		||||
    item_type_name: &'static str,
 | 
			
		||||
    item_type_path: TypePathTable,
 | 
			
		||||
    item_type_id: TypeId,
 | 
			
		||||
    capacity: usize,
 | 
			
		||||
    #[cfg(feature = "documentation")]
 | 
			
		||||
@ -93,11 +93,11 @@ impl ArrayInfo {
 | 
			
		||||
    ///
 | 
			
		||||
    /// * `capacity`: The maximum capacity of the underlying array.
 | 
			
		||||
    ///
 | 
			
		||||
    pub fn new<TArray: Array, TItem: Reflect>(capacity: usize) -> Self {
 | 
			
		||||
    pub fn new<TArray: Array + TypePath, TItem: Reflect + TypePath>(capacity: usize) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            type_name: std::any::type_name::<TArray>(),
 | 
			
		||||
            type_path: TypePathTable::of::<TArray>(),
 | 
			
		||||
            type_id: TypeId::of::<TArray>(),
 | 
			
		||||
            item_type_name: std::any::type_name::<TItem>(),
 | 
			
		||||
            item_type_path: TypePathTable::of::<TItem>(),
 | 
			
		||||
            item_type_id: TypeId::of::<TItem>(),
 | 
			
		||||
            capacity,
 | 
			
		||||
            #[cfg(feature = "documentation")]
 | 
			
		||||
@ -116,11 +116,21 @@ impl ArrayInfo {
 | 
			
		||||
        self.capacity
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the array.
 | 
			
		||||
    /// A representation of the type path of the array.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn type_name(&self) -> &'static str {
 | 
			
		||||
        self.type_name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [stable, full type path] of the array.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// [stable, full type path]: TypePath
 | 
			
		||||
    /// [`type_path_table`]: Self::type_path_table
 | 
			
		||||
    pub fn type_path(&self) -> &'static str {
 | 
			
		||||
        self.type_path_table().path()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the array.
 | 
			
		||||
@ -133,11 +143,11 @@ impl ArrayInfo {
 | 
			
		||||
        TypeId::of::<T>() == self.type_id
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the array item.
 | 
			
		||||
    /// A representation of the type path of the array item.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn item_type_name(&self) -> &'static str {
 | 
			
		||||
        self.item_type_name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn item_type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.item_type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the array item.
 | 
			
		||||
@ -213,13 +223,6 @@ impl DynamicArray {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Reflect for DynamicArray {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
            .map(|info| info.type_name())
 | 
			
		||||
            .unwrap_or_else(|| std::any::type_name::<Self>())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
 | 
			
		||||
@ -288,13 +288,6 @@ impl Enum for DynamicEnum {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Reflect for DynamicEnum {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
            .map(|info| info.type_name())
 | 
			
		||||
            .unwrap_or_default()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
@ -376,7 +369,7 @@ impl Reflect for DynamicEnum {
 | 
			
		||||
                self.set_variant(value.variant_name(), dyn_variant);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("`{}` is not an enum", value.type_name());
 | 
			
		||||
            panic!("`{}` is not an enum", value.reflect_type_path());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
use crate::{DynamicEnum, Reflect, VariantInfo, VariantType};
 | 
			
		||||
use crate::{DynamicEnum, Reflect, TypePath, TypePathTable, VariantInfo, VariantType};
 | 
			
		||||
use bevy_utils::HashMap;
 | 
			
		||||
use std::any::{Any, TypeId};
 | 
			
		||||
use std::slice::Iter;
 | 
			
		||||
@ -126,15 +126,14 @@ pub trait Enum: Reflect {
 | 
			
		||||
    }
 | 
			
		||||
    /// Returns the full path to the current variant.
 | 
			
		||||
    fn variant_path(&self) -> String {
 | 
			
		||||
        format!("{}::{}", self.type_name(), self.variant_name())
 | 
			
		||||
        format!("{}::{}", self.reflect_type_path(), self.variant_name())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// A container for compile-time enum info, used by [`TypeInfo`](crate::TypeInfo).
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct EnumInfo {
 | 
			
		||||
    name: &'static str,
 | 
			
		||||
    type_name: &'static str,
 | 
			
		||||
    type_path: TypePathTable,
 | 
			
		||||
    type_id: TypeId,
 | 
			
		||||
    variants: Box<[VariantInfo]>,
 | 
			
		||||
    variant_names: Box<[&'static str]>,
 | 
			
		||||
@ -148,10 +147,9 @@ impl EnumInfo {
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Arguments
 | 
			
		||||
    ///
 | 
			
		||||
    /// * `name`: The name of this enum (_without_ generics or lifetimes)
 | 
			
		||||
    /// * `variants`: The variants of this enum in the order they are defined
 | 
			
		||||
    ///
 | 
			
		||||
    pub fn new<TEnum: Enum>(name: &'static str, variants: &[VariantInfo]) -> Self {
 | 
			
		||||
    pub fn new<TEnum: Enum + TypePath>(variants: &[VariantInfo]) -> Self {
 | 
			
		||||
        let variant_indices = variants
 | 
			
		||||
            .iter()
 | 
			
		||||
            .enumerate()
 | 
			
		||||
@ -161,8 +159,7 @@ impl EnumInfo {
 | 
			
		||||
        let variant_names = variants.iter().map(|variant| variant.name()).collect();
 | 
			
		||||
 | 
			
		||||
        Self {
 | 
			
		||||
            name,
 | 
			
		||||
            type_name: std::any::type_name::<TEnum>(),
 | 
			
		||||
            type_path: TypePathTable::of::<TEnum>(),
 | 
			
		||||
            type_id: TypeId::of::<TEnum>(),
 | 
			
		||||
            variants: variants.to_vec().into_boxed_slice(),
 | 
			
		||||
            variant_names,
 | 
			
		||||
@ -204,7 +201,7 @@ impl EnumInfo {
 | 
			
		||||
    ///
 | 
			
		||||
    /// This does _not_ check if the given variant exists.
 | 
			
		||||
    pub fn variant_path(&self, name: &str) -> String {
 | 
			
		||||
        format!("{}::{name}", self.type_name())
 | 
			
		||||
        format!("{}::{name}", self.type_path())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Checks if a variant with the given name exists within this enum.
 | 
			
		||||
@ -222,20 +219,21 @@ impl EnumInfo {
 | 
			
		||||
        self.variants.len()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The name of the enum.
 | 
			
		||||
    /// A representation of the type path of the value.
 | 
			
		||||
    ///
 | 
			
		||||
    /// This does _not_ include any generics or lifetimes.
 | 
			
		||||
    ///
 | 
			
		||||
    /// For example, `foo::bar::Baz<'a, T>` would simply be `Baz`.
 | 
			
		||||
    pub fn name(&self) -> &'static str {
 | 
			
		||||
        self.name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the enum.
 | 
			
		||||
    /// The [stable, full type path] of the value.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn type_name(&self) -> &'static str {
 | 
			
		||||
        self.type_name
 | 
			
		||||
    /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// [stable, full type path]: TypePath
 | 
			
		||||
    /// [`type_path_table`]: Self::type_path_table
 | 
			
		||||
    pub fn type_path(&self) -> &'static str {
 | 
			
		||||
        self.type_path_table().path()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the enum.
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,15 @@ mod tests {
 | 
			
		||||
        let info = MyEnum::type_info();
 | 
			
		||||
        if let TypeInfo::Enum(info) = info {
 | 
			
		||||
            assert!(info.is::<MyEnum>(), "expected type to be `MyEnum`");
 | 
			
		||||
            assert_eq!(std::any::type_name::<MyEnum>(), info.type_name());
 | 
			
		||||
            assert_eq!(MyEnum::type_path(), info.type_path());
 | 
			
		||||
            assert_eq!(MyEnum::type_path(), info.type_path_table().path());
 | 
			
		||||
            assert_eq!(MyEnum::type_ident(), info.type_path_table().ident());
 | 
			
		||||
            assert_eq!(MyEnum::module_path(), info.type_path_table().module_path());
 | 
			
		||||
            assert_eq!(MyEnum::crate_name(), info.type_path_table().crate_name());
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                MyEnum::short_type_path(),
 | 
			
		||||
                info.type_path_table().short_path()
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // === MyEnum::A === //
 | 
			
		||||
            assert_eq!("A", info.variant_at(0).unwrap().name());
 | 
			
		||||
@ -275,7 +283,7 @@ mod tests {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    #[should_panic(expected = "`((usize, i32))` is not an enum")]
 | 
			
		||||
    #[should_panic(expected = "`bevy_reflect::DynamicTuple` is not an enum")]
 | 
			
		||||
    fn applying_non_enum_should_panic() {
 | 
			
		||||
        let mut value = MyEnum::B(0, 0);
 | 
			
		||||
        let mut dyn_tuple = DynamicTuple::default();
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,11 @@
 | 
			
		||||
use crate::Reflect;
 | 
			
		||||
use crate::{Reflect, TypePath, TypePathTable};
 | 
			
		||||
use std::any::{Any, TypeId};
 | 
			
		||||
 | 
			
		||||
/// The named field of a reflected struct.
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct NamedField {
 | 
			
		||||
    name: &'static str,
 | 
			
		||||
    type_name: &'static str,
 | 
			
		||||
    type_path: TypePathTable,
 | 
			
		||||
    type_id: TypeId,
 | 
			
		||||
    #[cfg(feature = "documentation")]
 | 
			
		||||
    docs: Option<&'static str>,
 | 
			
		||||
@ -13,10 +13,10 @@ pub struct NamedField {
 | 
			
		||||
 | 
			
		||||
impl NamedField {
 | 
			
		||||
    /// Create a new [`NamedField`].
 | 
			
		||||
    pub fn new<T: Reflect>(name: &'static str) -> Self {
 | 
			
		||||
    pub fn new<T: Reflect + TypePath>(name: &'static str) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            name,
 | 
			
		||||
            type_name: std::any::type_name::<T>(),
 | 
			
		||||
            type_path: TypePathTable::of::<T>(),
 | 
			
		||||
            type_id: TypeId::of::<T>(),
 | 
			
		||||
            #[cfg(feature = "documentation")]
 | 
			
		||||
            docs: None,
 | 
			
		||||
@ -34,11 +34,21 @@ impl NamedField {
 | 
			
		||||
        self.name
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the field.
 | 
			
		||||
    /// A representation of the type path of the field.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn type_name(&self) -> &'static str {
 | 
			
		||||
        self.type_name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [stable, full type path] of the field.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// [stable, full type path]: TypePath
 | 
			
		||||
    /// [`type_path_table`]: Self::type_path_table
 | 
			
		||||
    pub fn type_path(&self) -> &'static str {
 | 
			
		||||
        self.type_path_table().path()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the field.
 | 
			
		||||
@ -62,17 +72,17 @@ impl NamedField {
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct UnnamedField {
 | 
			
		||||
    index: usize,
 | 
			
		||||
    type_name: &'static str,
 | 
			
		||||
    type_path: TypePathTable,
 | 
			
		||||
    type_id: TypeId,
 | 
			
		||||
    #[cfg(feature = "documentation")]
 | 
			
		||||
    docs: Option<&'static str>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl UnnamedField {
 | 
			
		||||
    pub fn new<T: Reflect>(index: usize) -> Self {
 | 
			
		||||
    pub fn new<T: Reflect + TypePath>(index: usize) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            index,
 | 
			
		||||
            type_name: std::any::type_name::<T>(),
 | 
			
		||||
            type_path: TypePathTable::of::<T>(),
 | 
			
		||||
            type_id: TypeId::of::<T>(),
 | 
			
		||||
            #[cfg(feature = "documentation")]
 | 
			
		||||
            docs: None,
 | 
			
		||||
@ -90,11 +100,21 @@ impl UnnamedField {
 | 
			
		||||
        self.index
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the field.
 | 
			
		||||
    /// A representation of the type path of the field.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn type_name(&self) -> &'static str {
 | 
			
		||||
        self.type_name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [stable, full type path] of the field.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// [stable, full type path]: TypePath
 | 
			
		||||
    /// [`type_path_table`]: Self::type_path_table
 | 
			
		||||
    pub fn type_path(&self) -> &'static str {
 | 
			
		||||
        self.type_path_table().path()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the field.
 | 
			
		||||
 | 
			
		||||
@ -75,7 +75,7 @@ pub trait FromReflect: Reflect + Sized {
 | 
			
		||||
/// # Example
 | 
			
		||||
///
 | 
			
		||||
/// ```
 | 
			
		||||
/// # use bevy_reflect::{DynamicTupleStruct, Reflect, ReflectFromReflect, Typed, TypeRegistry};
 | 
			
		||||
/// # use bevy_reflect::{DynamicTupleStruct, Reflect, ReflectFromReflect, Typed, TypeRegistry, TypePath};
 | 
			
		||||
/// # #[derive(Reflect, PartialEq, Eq, Debug)]
 | 
			
		||||
/// # struct Foo(#[reflect(default = "default_value")] usize);
 | 
			
		||||
/// # fn default_value() -> usize { 123 }
 | 
			
		||||
@ -85,7 +85,7 @@ pub trait FromReflect: Reflect + Sized {
 | 
			
		||||
/// let mut reflected = DynamicTupleStruct::default();
 | 
			
		||||
/// reflected.set_represented_type(Some(<Foo as Typed>::type_info()));
 | 
			
		||||
///
 | 
			
		||||
/// let registration = registry.get_with_name(reflected.type_name()).unwrap();
 | 
			
		||||
/// let registration = registry.get_with_type_path(<Foo as TypePath>::type_path()).unwrap();
 | 
			
		||||
/// let rfr = registration.data::<ReflectFromReflect>().unwrap();
 | 
			
		||||
///
 | 
			
		||||
/// let concrete: Box<dyn Reflect> = rfr.from_reflect(&reflected).unwrap();
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ use crate::{
 | 
			
		||||
 | 
			
		||||
impl<T: smallvec::Array + TypePath + Send + Sync> List for SmallVec<T>
 | 
			
		||||
where
 | 
			
		||||
    T::Item: FromReflect,
 | 
			
		||||
    T::Item: FromReflect + TypePath,
 | 
			
		||||
{
 | 
			
		||||
    fn get(&self, index: usize) -> Option<&dyn Reflect> {
 | 
			
		||||
        if index < SmallVec::len(self) {
 | 
			
		||||
@ -34,7 +34,7 @@ where
 | 
			
		||||
            <T as smallvec::Array>::Item::from_reflect(&*value).unwrap_or_else(|| {
 | 
			
		||||
                panic!(
 | 
			
		||||
                    "Attempted to insert invalid value of type {}.",
 | 
			
		||||
                    value.type_name()
 | 
			
		||||
                    value.reflect_type_path()
 | 
			
		||||
                )
 | 
			
		||||
            })
 | 
			
		||||
        });
 | 
			
		||||
@ -50,7 +50,7 @@ where
 | 
			
		||||
            <T as smallvec::Array>::Item::from_reflect(&*value).unwrap_or_else(|| {
 | 
			
		||||
                panic!(
 | 
			
		||||
                    "Attempted to push invalid value of type {}.",
 | 
			
		||||
                    value.type_name()
 | 
			
		||||
                    value.reflect_type_path()
 | 
			
		||||
                )
 | 
			
		||||
            })
 | 
			
		||||
        });
 | 
			
		||||
@ -78,12 +78,8 @@ where
 | 
			
		||||
 | 
			
		||||
impl<T: smallvec::Array + TypePath + Send + Sync> Reflect for SmallVec<T>
 | 
			
		||||
where
 | 
			
		||||
    T::Item: FromReflect,
 | 
			
		||||
    T::Item: FromReflect + TypePath,
 | 
			
		||||
{
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        std::any::type_name::<Self>()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
        Some(<Self as Typed>::type_info())
 | 
			
		||||
    }
 | 
			
		||||
@ -144,7 +140,7 @@ where
 | 
			
		||||
 | 
			
		||||
impl<T: smallvec::Array + TypePath + Send + Sync + 'static> Typed for SmallVec<T>
 | 
			
		||||
where
 | 
			
		||||
    T::Item: FromReflect,
 | 
			
		||||
    T::Item: FromReflect + TypePath,
 | 
			
		||||
{
 | 
			
		||||
    fn type_info() -> &'static TypeInfo {
 | 
			
		||||
        static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
 | 
			
		||||
@ -152,11 +148,11 @@ where
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl_type_path!(::smallvec::SmallVec<T: smallvec::Array + TypePath + Send + Sync>);
 | 
			
		||||
impl_type_path!(::smallvec::SmallVec<T: smallvec::Array>);
 | 
			
		||||
 | 
			
		||||
impl<T: smallvec::Array + TypePath + Send + Sync> FromReflect for SmallVec<T>
 | 
			
		||||
where
 | 
			
		||||
    T::Item: FromReflect,
 | 
			
		||||
    T::Item: FromReflect + TypePath,
 | 
			
		||||
{
 | 
			
		||||
    fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
 | 
			
		||||
        if let ReflectRef::List(ref_list) = reflect.reflect_ref() {
 | 
			
		||||
@ -173,7 +169,7 @@ where
 | 
			
		||||
 | 
			
		||||
impl<T: smallvec::Array + TypePath + Send + Sync> GetTypeRegistration for SmallVec<T>
 | 
			
		||||
where
 | 
			
		||||
    T::Item: FromReflect,
 | 
			
		||||
    T::Item: FromReflect + TypePath,
 | 
			
		||||
{
 | 
			
		||||
    fn get_type_registration() -> TypeRegistration {
 | 
			
		||||
        let mut registration = TypeRegistration::of::<SmallVec<T>>();
 | 
			
		||||
 | 
			
		||||
@ -79,7 +79,8 @@ impl_reflect_value!(isize(
 | 
			
		||||
));
 | 
			
		||||
impl_reflect_value!(f32(Debug, PartialEq, Serialize, Deserialize, Default));
 | 
			
		||||
impl_reflect_value!(f64(Debug, PartialEq, Serialize, Deserialize, Default));
 | 
			
		||||
impl_reflect_value!(String(
 | 
			
		||||
impl_type_path!(str);
 | 
			
		||||
impl_reflect_value!(::alloc::string::String(
 | 
			
		||||
    Debug,
 | 
			
		||||
    Hash,
 | 
			
		||||
    PartialEq,
 | 
			
		||||
@ -232,7 +233,7 @@ macro_rules! impl_reflect_for_veclike {
 | 
			
		||||
                    T::from_reflect(&*value).unwrap_or_else(|| {
 | 
			
		||||
                        panic!(
 | 
			
		||||
                            "Attempted to insert invalid value of type {}.",
 | 
			
		||||
                            value.type_name()
 | 
			
		||||
                            value.reflect_type_path()
 | 
			
		||||
                        )
 | 
			
		||||
                    })
 | 
			
		||||
                });
 | 
			
		||||
@ -247,7 +248,7 @@ macro_rules! impl_reflect_for_veclike {
 | 
			
		||||
                let value = T::take_from_reflect(value).unwrap_or_else(|value| {
 | 
			
		||||
                    panic!(
 | 
			
		||||
                        "Attempted to push invalid value of type {}.",
 | 
			
		||||
                        value.type_name()
 | 
			
		||||
                        value.reflect_type_path()
 | 
			
		||||
                    )
 | 
			
		||||
                });
 | 
			
		||||
                $push(self, value);
 | 
			
		||||
@ -276,10 +277,6 @@ macro_rules! impl_reflect_for_veclike {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        impl<T: FromReflect + TypePath> Reflect for $ty {
 | 
			
		||||
            fn type_name(&self) -> &str {
 | 
			
		||||
                std::any::type_name::<Self>()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
                Some(<Self as Typed>::type_info())
 | 
			
		||||
            }
 | 
			
		||||
@ -349,7 +346,7 @@ macro_rules! impl_reflect_for_veclike {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        impl_type_path!($ty where T: FromReflect);
 | 
			
		||||
        impl_type_path!($ty);
 | 
			
		||||
 | 
			
		||||
        impl<T: FromReflect + TypePath> GetTypeRegistration for $ty {
 | 
			
		||||
            fn get_type_registration() -> TypeRegistration {
 | 
			
		||||
@ -448,7 +445,10 @@ macro_rules! impl_reflect_for_hashmap {
 | 
			
		||||
                dynamic_map.set_represented_type(self.get_represented_type_info());
 | 
			
		||||
                for (k, v) in self {
 | 
			
		||||
                    let key = K::from_reflect(k).unwrap_or_else(|| {
 | 
			
		||||
                        panic!("Attempted to clone invalid key of type {}.", k.type_name())
 | 
			
		||||
                        panic!(
 | 
			
		||||
                            "Attempted to clone invalid key of type {}.",
 | 
			
		||||
                            k.reflect_type_path()
 | 
			
		||||
                        )
 | 
			
		||||
                    });
 | 
			
		||||
                    dynamic_map.insert_boxed(Box::new(key), v.clone_value());
 | 
			
		||||
                }
 | 
			
		||||
@ -463,13 +463,13 @@ macro_rules! impl_reflect_for_hashmap {
 | 
			
		||||
                let key = K::take_from_reflect(key).unwrap_or_else(|key| {
 | 
			
		||||
                    panic!(
 | 
			
		||||
                        "Attempted to insert invalid key of type {}.",
 | 
			
		||||
                        key.type_name()
 | 
			
		||||
                        key.reflect_type_path()
 | 
			
		||||
                    )
 | 
			
		||||
                });
 | 
			
		||||
                let value = V::take_from_reflect(value).unwrap_or_else(|value| {
 | 
			
		||||
                    panic!(
 | 
			
		||||
                        "Attempted to insert invalid value of type {}.",
 | 
			
		||||
                        value.type_name()
 | 
			
		||||
                        value.reflect_type_path()
 | 
			
		||||
                    )
 | 
			
		||||
                });
 | 
			
		||||
                self.insert(key, value)
 | 
			
		||||
@ -494,10 +494,6 @@ macro_rules! impl_reflect_for_hashmap {
 | 
			
		||||
            V: FromReflect + TypePath,
 | 
			
		||||
            S: TypePath + BuildHasher + Send + Sync,
 | 
			
		||||
        {
 | 
			
		||||
            fn type_name(&self) -> &str {
 | 
			
		||||
                std::any::type_name::<Self>()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
                Some(<Self as Typed>::type_info())
 | 
			
		||||
            }
 | 
			
		||||
@ -607,23 +603,11 @@ macro_rules! impl_reflect_for_hashmap {
 | 
			
		||||
 | 
			
		||||
impl_reflect_for_hashmap!(::std::collections::HashMap<K, V, S>);
 | 
			
		||||
impl_type_path!(::std::collections::hash_map::RandomState);
 | 
			
		||||
impl_type_path!(
 | 
			
		||||
    ::std::collections::HashMap<K, V, S>
 | 
			
		||||
    where
 | 
			
		||||
        K: FromReflect + Eq + Hash + ?Sized,
 | 
			
		||||
        V: FromReflect + ?Sized,
 | 
			
		||||
        S: BuildHasher + Send + Sync + 'static,
 | 
			
		||||
);
 | 
			
		||||
impl_type_path!(::std::collections::HashMap<K, V, S>);
 | 
			
		||||
 | 
			
		||||
impl_reflect_for_hashmap!(bevy_utils::hashbrown::HashMap<K, V, S>);
 | 
			
		||||
impl_type_path!(::bevy_utils::hashbrown::hash_map::DefaultHashBuilder);
 | 
			
		||||
impl_type_path!(
 | 
			
		||||
    ::bevy_utils::hashbrown::HashMap<K, V, S>
 | 
			
		||||
    where
 | 
			
		||||
        K: FromReflect + Eq + Hash + ?Sized,
 | 
			
		||||
        V: FromReflect + ?Sized,
 | 
			
		||||
        S: BuildHasher + Send + Sync + 'static,
 | 
			
		||||
);
 | 
			
		||||
impl_type_path!(::bevy_utils::hashbrown::HashMap<K, V, S>);
 | 
			
		||||
 | 
			
		||||
impl<T: Reflect + TypePath, const N: usize> Array for [T; N] {
 | 
			
		||||
    #[inline]
 | 
			
		||||
@ -655,11 +639,6 @@ impl<T: Reflect + TypePath, const N: usize> Array for [T; N] {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Reflect + TypePath, const N: usize> Reflect for [T; N] {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        std::any::type_name::<Self>()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
        Some(<Self as Typed>::type_info())
 | 
			
		||||
    }
 | 
			
		||||
@ -757,7 +736,7 @@ impl<T: Reflect + TypePath, const N: usize> Typed for [T; N] {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Reflect + TypePath, const N: usize> TypePath for [T; N] {
 | 
			
		||||
impl<T: TypePath, const N: usize> TypePath for [T; N] {
 | 
			
		||||
    fn type_path() -> &'static str {
 | 
			
		||||
        static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
        CELL.get_or_insert::<Self, _>(|| format!("[{t}; {N}]", t = T::type_path()))
 | 
			
		||||
@ -871,11 +850,6 @@ impl<T: FromReflect + TypePath> Enum for Option<T> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: FromReflect + TypePath> Reflect for Option<T> {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        std::any::type_name::<Self>()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
        Some(<Self as Typed>::type_info())
 | 
			
		||||
@ -929,7 +903,7 @@ impl<T: FromReflect + TypePath> Reflect for Option<T> {
 | 
			
		||||
                                .unwrap_or_else(|| {
 | 
			
		||||
                                    panic!(
 | 
			
		||||
                                        "Field in `Some` variant of {} should exist",
 | 
			
		||||
                                        std::any::type_name::<Option<T>>()
 | 
			
		||||
                                        Self::type_path()
 | 
			
		||||
                                    )
 | 
			
		||||
                                })
 | 
			
		||||
                                .clone_value(),
 | 
			
		||||
@ -937,8 +911,8 @@ impl<T: FromReflect + TypePath> Reflect for Option<T> {
 | 
			
		||||
                        .unwrap_or_else(|_| {
 | 
			
		||||
                            panic!(
 | 
			
		||||
                                "Field in `Some` variant of {} should be of type {}",
 | 
			
		||||
                                std::any::type_name::<Option<T>>(),
 | 
			
		||||
                                std::any::type_name::<T>()
 | 
			
		||||
                                Self::type_path(),
 | 
			
		||||
                                T::type_path()
 | 
			
		||||
                            )
 | 
			
		||||
                        });
 | 
			
		||||
                        *self = Some(field);
 | 
			
		||||
@ -946,7 +920,7 @@ impl<T: FromReflect + TypePath> Reflect for Option<T> {
 | 
			
		||||
                    "None" => {
 | 
			
		||||
                        *self = None;
 | 
			
		||||
                    }
 | 
			
		||||
                    _ => panic!("Enum is not a {}.", std::any::type_name::<Self>()),
 | 
			
		||||
                    _ => panic!("Enum is not a {}.", Self::type_path()),
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -995,7 +969,7 @@ impl<T: FromReflect + TypePath> FromReflect for Option<T> {
 | 
			
		||||
                            .unwrap_or_else(|| {
 | 
			
		||||
                                panic!(
 | 
			
		||||
                                    "Field in `Some` variant of {} should exist",
 | 
			
		||||
                                    std::any::type_name::<Option<T>>()
 | 
			
		||||
                                    Option::<T>::type_path()
 | 
			
		||||
                                )
 | 
			
		||||
                            })
 | 
			
		||||
                            .clone_value(),
 | 
			
		||||
@ -1003,8 +977,8 @@ impl<T: FromReflect + TypePath> FromReflect for Option<T> {
 | 
			
		||||
                    .unwrap_or_else(|_| {
 | 
			
		||||
                        panic!(
 | 
			
		||||
                            "Field in `Some` variant of {} should be of type {}",
 | 
			
		||||
                            std::any::type_name::<Option<T>>(),
 | 
			
		||||
                            std::any::type_name::<T>()
 | 
			
		||||
                            Option::<T>::type_path(),
 | 
			
		||||
                            T::type_path()
 | 
			
		||||
                        )
 | 
			
		||||
                    });
 | 
			
		||||
                    Some(Some(field))
 | 
			
		||||
@ -1013,7 +987,7 @@ impl<T: FromReflect + TypePath> FromReflect for Option<T> {
 | 
			
		||||
                name => panic!(
 | 
			
		||||
                    "variant with name `{}` does not exist on enum `{}`",
 | 
			
		||||
                    name,
 | 
			
		||||
                    std::any::type_name::<Self>()
 | 
			
		||||
                    Self::type_path()
 | 
			
		||||
                ),
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
@ -1029,21 +1003,38 @@ impl<T: FromReflect + TypePath> Typed for Option<T> {
 | 
			
		||||
            let none_variant = VariantInfo::Unit(UnitVariantInfo::new("None"));
 | 
			
		||||
            let some_variant =
 | 
			
		||||
                VariantInfo::Tuple(TupleVariantInfo::new("Some", &[UnnamedField::new::<T>(0)]));
 | 
			
		||||
            TypeInfo::Enum(EnumInfo::new::<Self>(
 | 
			
		||||
                "Option",
 | 
			
		||||
                &[none_variant, some_variant],
 | 
			
		||||
            ))
 | 
			
		||||
            TypeInfo::Enum(EnumInfo::new::<Self>(&[none_variant, some_variant]))
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl_type_path!(::core::option::Option<T: FromReflect + TypePath>);
 | 
			
		||||
impl_type_path!(::core::option::Option<T>);
 | 
			
		||||
 | 
			
		||||
impl Reflect for Cow<'static, str> {
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        std::any::type_name::<Self>()
 | 
			
		||||
impl<T: TypePath + ?Sized> TypePath for &'static T {
 | 
			
		||||
    fn type_path() -> &'static str {
 | 
			
		||||
        static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
        CELL.get_or_insert::<Self, _>(|| format!("&{}", T::type_path()))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn short_type_path() -> &'static str {
 | 
			
		||||
        static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
        CELL.get_or_insert::<Self, _>(|| format!("&{}", T::short_type_path()))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: TypePath + ?Sized> TypePath for &'static mut T {
 | 
			
		||||
    fn type_path() -> &'static str {
 | 
			
		||||
        static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
        CELL.get_or_insert::<Self, _>(|| format!("&mut {}", T::type_path()))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn short_type_path() -> &'static str {
 | 
			
		||||
        static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
        CELL.get_or_insert::<Self, _>(|| format!("&mut {}", T::short_type_path()))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Reflect for Cow<'static, str> {
 | 
			
		||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
        Some(<Self as Typed>::type_info())
 | 
			
		||||
    }
 | 
			
		||||
@ -1077,7 +1068,7 @@ impl Reflect for Cow<'static, str> {
 | 
			
		||||
        if let Some(value) = value.downcast_ref::<Self>() {
 | 
			
		||||
            *self = value.clone();
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("Value is not a {}.", std::any::type_name::<Self>());
 | 
			
		||||
            panic!("Value is not a {}.", Self::type_path());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1126,30 +1117,6 @@ impl Typed for Cow<'static, str> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TypePath for Cow<'static, str> {
 | 
			
		||||
    fn type_path() -> &'static str {
 | 
			
		||||
        static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
        CELL.get_or_insert::<Self, _>(|| "std::borrow::Cow::<str>".to_owned())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn short_type_path() -> &'static str {
 | 
			
		||||
        static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
        CELL.get_or_insert::<Self, _>(|| "Cow<str>".to_owned())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn type_ident() -> Option<&'static str> {
 | 
			
		||||
        Some("Cow")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn crate_name() -> Option<&'static str> {
 | 
			
		||||
        Some("std")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn module_path() -> Option<&'static str> {
 | 
			
		||||
        Some("std::borrow")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl GetTypeRegistration for Cow<'static, str> {
 | 
			
		||||
    fn get_type_registration() -> TypeRegistration {
 | 
			
		||||
        let mut registration = TypeRegistration::of::<Cow<'static, str>>();
 | 
			
		||||
@ -1171,8 +1138,6 @@ impl FromReflect for Cow<'static, str> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: PathOnly> PathOnly for [T] where [T]: ToOwned {}
 | 
			
		||||
 | 
			
		||||
impl<T: TypePath> TypePath for [T]
 | 
			
		||||
where
 | 
			
		||||
    [T]: ToOwned,
 | 
			
		||||
@ -1188,8 +1153,6 @@ where
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: ToOwned> PathOnly for T {}
 | 
			
		||||
 | 
			
		||||
impl<T: FromReflect + Clone + TypePath> List for Cow<'static, [T]> {
 | 
			
		||||
    fn get(&self, index: usize) -> Option<&dyn Reflect> {
 | 
			
		||||
        self.as_ref().get(index).map(|x| x as &dyn Reflect)
 | 
			
		||||
@ -1221,7 +1184,7 @@ impl<T: FromReflect + Clone + TypePath> List for Cow<'static, [T]> {
 | 
			
		||||
            T::from_reflect(&*value).unwrap_or_else(|| {
 | 
			
		||||
                panic!(
 | 
			
		||||
                    "Attempted to insert invalid value of type {}.",
 | 
			
		||||
                    value.type_name()
 | 
			
		||||
                    value.reflect_type_path()
 | 
			
		||||
                )
 | 
			
		||||
            })
 | 
			
		||||
        });
 | 
			
		||||
@ -1236,7 +1199,7 @@ impl<T: FromReflect + Clone + TypePath> List for Cow<'static, [T]> {
 | 
			
		||||
        let value = T::take_from_reflect(value).unwrap_or_else(|value| {
 | 
			
		||||
            panic!(
 | 
			
		||||
                "Attempted to push invalid value of type {}.",
 | 
			
		||||
                value.type_name()
 | 
			
		||||
                value.reflect_type_path()
 | 
			
		||||
            )
 | 
			
		||||
        });
 | 
			
		||||
        self.to_mut().push(value);
 | 
			
		||||
@ -1250,10 +1213,6 @@ impl<T: FromReflect + Clone + TypePath> List for Cow<'static, [T]> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: FromReflect + Clone + TypePath> Reflect for Cow<'static, [T]> {
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        std::any::type_name::<Self>()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn into_any(self: Box<Self>) -> Box<dyn Any> {
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
@ -1344,10 +1303,6 @@ impl<T: FromReflect + Clone + TypePath> FromReflect for Cow<'static, [T]> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Reflect for &'static Path {
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        std::any::type_name::<Self>()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
        Some(<Self as Typed>::type_info())
 | 
			
		||||
    }
 | 
			
		||||
@ -1381,7 +1336,7 @@ impl Reflect for &'static Path {
 | 
			
		||||
        if let Some(&value) = value.downcast_ref::<Self>() {
 | 
			
		||||
            *self = value;
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("Value is not a {}.", std::any::type_name::<Self>());
 | 
			
		||||
            panic!("Value is not a {}.", Self::type_path());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1430,18 +1385,6 @@ impl Typed for &'static Path {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TypePath for &'static Path {
 | 
			
		||||
    fn type_path() -> &'static str {
 | 
			
		||||
        static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
        CELL.get_or_insert::<Self, _>(|| "&std::path::Path".to_owned())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn short_type_path() -> &'static str {
 | 
			
		||||
        static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
        CELL.get_or_insert::<Self, _>(|| "&Path".to_owned())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl GetTypeRegistration for &'static Path {
 | 
			
		||||
    fn get_type_registration() -> TypeRegistration {
 | 
			
		||||
        let mut registration = TypeRegistration::of::<Self>();
 | 
			
		||||
@ -1457,10 +1400,6 @@ impl FromReflect for &'static Path {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Reflect for Cow<'static, Path> {
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        std::any::type_name::<Self>()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
        Some(<Self as Typed>::type_info())
 | 
			
		||||
    }
 | 
			
		||||
@ -1494,7 +1433,7 @@ impl Reflect for Cow<'static, Path> {
 | 
			
		||||
        if let Some(value) = value.downcast_ref::<Self>() {
 | 
			
		||||
            *self = value.clone();
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("Value is not a {}.", std::any::type_name::<Self>());
 | 
			
		||||
            panic!("Value is not a {}.", Self::type_path());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1547,10 +1486,8 @@ impl Typed for Cow<'static, Path> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
trait PathOnly: ToOwned {}
 | 
			
		||||
impl PathOnly for Path {}
 | 
			
		||||
impl_type_path!(::alloc::borrow::Cow<'a: 'static, T: PathOnly + ?Sized>);
 | 
			
		||||
impl_type_path!(::std::path::Path);
 | 
			
		||||
impl_type_path!(::alloc::borrow::Cow<'a: 'static, T: ToOwned + ?Sized>);
 | 
			
		||||
 | 
			
		||||
impl FromReflect for Cow<'static, Path> {
 | 
			
		||||
    fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
 | 
			
		||||
 | 
			
		||||
@ -335,7 +335,7 @@
 | 
			
		||||
//! The general entry point are the "untyped" versions of these structs.
 | 
			
		||||
//! These will automatically extract the type information and pass them into their respective "typed" version.
 | 
			
		||||
//!
 | 
			
		||||
//! The output of the `ReflectSerializer` will be a map, where the key is the [type name]
 | 
			
		||||
//! The output of the `ReflectSerializer` will be a map, where the key is the [type path]
 | 
			
		||||
//! and the value is the serialized data.
 | 
			
		||||
//! The `TypedReflectSerializer` will simply output the serialized data.
 | 
			
		||||
//!
 | 
			
		||||
@ -456,7 +456,7 @@
 | 
			
		||||
//! [`TypedReflectDeserializer`]: serde::TypedReflectDeserializer
 | 
			
		||||
//! [registry]: TypeRegistry
 | 
			
		||||
//! [type information]: TypeInfo
 | 
			
		||||
//! [type name]: Reflect::type_name
 | 
			
		||||
//! [type path]: TypePath
 | 
			
		||||
//! [type registry]: TypeRegistry
 | 
			
		||||
//! [`bevy_math`]: https://docs.rs/bevy_math/latest/bevy_math/
 | 
			
		||||
//! [`glam`]: https://docs.rs/glam/latest/glam/
 | 
			
		||||
@ -1131,28 +1131,28 @@ mod tests {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn dynamic_names() {
 | 
			
		||||
    fn not_dynamic_names() {
 | 
			
		||||
        let list = Vec::<usize>::new();
 | 
			
		||||
        let dyn_list = list.clone_dynamic();
 | 
			
		||||
        assert_eq!(dyn_list.type_name(), std::any::type_name::<Vec<usize>>());
 | 
			
		||||
        assert_ne!(dyn_list.reflect_type_path(), Vec::<usize>::type_path());
 | 
			
		||||
 | 
			
		||||
        let array = [b'0'; 4];
 | 
			
		||||
        let dyn_array = array.clone_dynamic();
 | 
			
		||||
        assert_eq!(dyn_array.type_name(), std::any::type_name::<[u8; 4]>());
 | 
			
		||||
        assert_ne!(dyn_array.reflect_type_path(), <[u8; 4]>::type_path());
 | 
			
		||||
 | 
			
		||||
        let map = HashMap::<usize, String>::default();
 | 
			
		||||
        let dyn_map = map.clone_dynamic();
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            dyn_map.type_name(),
 | 
			
		||||
            std::any::type_name::<HashMap<usize, String>>()
 | 
			
		||||
        assert_ne!(
 | 
			
		||||
            dyn_map.reflect_type_path(),
 | 
			
		||||
            HashMap::<usize, String>::type_path()
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        let tuple = (0usize, "1".to_string(), 2.0f32);
 | 
			
		||||
        let mut dyn_tuple = tuple.clone_dynamic();
 | 
			
		||||
        dyn_tuple.insert::<usize>(3);
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            dyn_tuple.type_name(),
 | 
			
		||||
            std::any::type_name::<(usize, String, f32, usize)>()
 | 
			
		||||
        assert_ne!(
 | 
			
		||||
            dyn_tuple.reflect_type_path(),
 | 
			
		||||
            <(usize, String, f32, usize)>::type_path()
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        #[derive(Reflect)]
 | 
			
		||||
@ -1161,18 +1161,27 @@ mod tests {
 | 
			
		||||
        }
 | 
			
		||||
        let struct_ = TestStruct { a: 0 };
 | 
			
		||||
        let dyn_struct = struct_.clone_dynamic();
 | 
			
		||||
        assert_eq!(dyn_struct.type_name(), std::any::type_name::<TestStruct>());
 | 
			
		||||
        assert_ne!(dyn_struct.reflect_type_path(), TestStruct::type_path());
 | 
			
		||||
 | 
			
		||||
        #[derive(Reflect)]
 | 
			
		||||
        struct TestTupleStruct(usize);
 | 
			
		||||
        let tuple_struct = TestTupleStruct(0);
 | 
			
		||||
        let dyn_tuple_struct = tuple_struct.clone_dynamic();
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            dyn_tuple_struct.type_name(),
 | 
			
		||||
            std::any::type_name::<TestTupleStruct>()
 | 
			
		||||
        assert_ne!(
 | 
			
		||||
            dyn_tuple_struct.reflect_type_path(),
 | 
			
		||||
            TestTupleStruct::type_path()
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    macro_rules! assert_type_paths {
 | 
			
		||||
        ($($ty:ty => $long:literal, $short:literal,)*) => {
 | 
			
		||||
            $(
 | 
			
		||||
                assert_eq!(<$ty as TypePath>::type_path(), $long);
 | 
			
		||||
                assert_eq!(<$ty as TypePath>::short_type_path(), $short);
 | 
			
		||||
            )*
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn reflect_type_path() {
 | 
			
		||||
        #[derive(TypePath)]
 | 
			
		||||
@ -1214,62 +1223,57 @@ mod tests {
 | 
			
		||||
        struct MacroNameG<T>(PhantomData<T>);
 | 
			
		||||
        impl_type_path!((in my_alias as MyMacroNameG) MacroNameG<T>);
 | 
			
		||||
 | 
			
		||||
        assert_eq!(Derive::type_path(), "bevy_reflect::tests::Derive");
 | 
			
		||||
        assert_eq!(DerivePath::type_path(), "my_alias::DerivePath");
 | 
			
		||||
        assert_eq!(DerivePathName::type_path(), "my_alias::MyDerivePathName");
 | 
			
		||||
        assert_type_paths! {
 | 
			
		||||
            Derive => "bevy_reflect::tests::Derive", "Derive",
 | 
			
		||||
            DerivePath => "my_alias::DerivePath", "DerivePath",
 | 
			
		||||
            DerivePathName => "my_alias::MyDerivePathName", "MyDerivePathName",
 | 
			
		||||
            DeriveG<Param> => "bevy_reflect::tests::DeriveG<bevy_reflect::tests::Param>", "DeriveG<Param>",
 | 
			
		||||
            DerivePathG<Param, 10> => "my_alias::DerivePathG<bevy_reflect::tests::Param, 10>", "DerivePathG<Param, 10>",
 | 
			
		||||
            DerivePathNameG<Param> => "my_alias::MyDerivePathNameG<bevy_reflect::tests::Param>", "MyDerivePathNameG<Param>",
 | 
			
		||||
            Macro => "my_alias::Macro", "Macro",
 | 
			
		||||
            MacroName => "my_alias::MyMacroName", "MyMacroName",
 | 
			
		||||
            MacroG<Param, 10> => "my_alias::MacroG<bevy_reflect::tests::Param, 10>", "MacroG<Param, 10>",
 | 
			
		||||
            MacroNameG<Param> => "my_alias::MyMacroNameG<bevy_reflect::tests::Param>", "MyMacroNameG<Param>",
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            DeriveG::<Param>::type_path(),
 | 
			
		||||
            "bevy_reflect::tests::DeriveG<bevy_reflect::tests::Param>"
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            DerivePathG::<Param, 10>::type_path(),
 | 
			
		||||
            "my_alias::DerivePathG<bevy_reflect::tests::Param, 10>"
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            DerivePathNameG::<Param>::type_path(),
 | 
			
		||||
            "my_alias::MyDerivePathNameG<bevy_reflect::tests::Param>"
 | 
			
		||||
        );
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn std_type_paths() {
 | 
			
		||||
        #[derive(Clone)]
 | 
			
		||||
        struct Type;
 | 
			
		||||
 | 
			
		||||
        assert_eq!(Macro::type_path(), "my_alias::Macro");
 | 
			
		||||
        assert_eq!(MacroName::type_path(), "my_alias::MyMacroName");
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            MacroG::<Param, 10>::type_path(),
 | 
			
		||||
            "my_alias::MacroG<bevy_reflect::tests::Param, 10>"
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            MacroNameG::<Param>::type_path(),
 | 
			
		||||
            "my_alias::MyMacroNameG<bevy_reflect::tests::Param>"
 | 
			
		||||
        );
 | 
			
		||||
        impl TypePath for Type {
 | 
			
		||||
            fn type_path() -> &'static str {
 | 
			
		||||
                // for brevity in tests
 | 
			
		||||
                "Long"
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        assert_eq!(Derive::short_type_path(), "Derive");
 | 
			
		||||
        assert_eq!(DerivePath::short_type_path(), "DerivePath");
 | 
			
		||||
        assert_eq!(DerivePathName::short_type_path(), "MyDerivePathName");
 | 
			
		||||
            fn short_type_path() -> &'static str {
 | 
			
		||||
                "Short"
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        assert_eq!(DeriveG::<Param>::short_type_path(), "DeriveG<Param>");
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            DerivePathG::<Param, 10>::short_type_path(),
 | 
			
		||||
            "DerivePathG<Param, 10>"
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            DerivePathNameG::<Param>::short_type_path(),
 | 
			
		||||
            "MyDerivePathNameG<Param>"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        assert_eq!(Macro::short_type_path(), "Macro");
 | 
			
		||||
        assert_eq!(MacroName::short_type_path(), "MyMacroName");
 | 
			
		||||
        assert_eq!(MacroG::<Param, 10>::short_type_path(), "MacroG<Param, 10>");
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            MacroNameG::<Param>::short_type_path(),
 | 
			
		||||
            "MyMacroNameG<Param>"
 | 
			
		||||
        );
 | 
			
		||||
        assert_type_paths! {
 | 
			
		||||
            u8 => "u8", "u8",
 | 
			
		||||
            Type => "Long", "Short",
 | 
			
		||||
            &Type => "&Long", "&Short",
 | 
			
		||||
            [Type] => "[Long]", "[Short]",
 | 
			
		||||
            &[Type] => "&[Long]", "&[Short]",
 | 
			
		||||
            [Type; 0] => "[Long; 0]", "[Short; 0]",
 | 
			
		||||
            [Type; 100] => "[Long; 100]", "[Short; 100]",
 | 
			
		||||
            () => "()", "()",
 | 
			
		||||
            (Type,) => "(Long,)", "(Short,)",
 | 
			
		||||
            (Type, Type) => "(Long, Long)", "(Short, Short)",
 | 
			
		||||
            (Type, Type, Type) => "(Long, Long, Long)", "(Short, Short, Short)",
 | 
			
		||||
            Cow<'static, Type> => "alloc::borrow::Cow<Long>", "Cow<Short>",
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn reflect_type_info() {
 | 
			
		||||
        // TypeInfo
 | 
			
		||||
        let info = i32::type_info();
 | 
			
		||||
        assert_eq!(std::any::type_name::<i32>(), info.type_name());
 | 
			
		||||
        assert_eq!(i32::type_path(), info.type_path());
 | 
			
		||||
        assert_eq!(std::any::TypeId::of::<i32>(), info.type_id());
 | 
			
		||||
 | 
			
		||||
        // TypeInfo (unsized)
 | 
			
		||||
@ -1293,21 +1297,15 @@ mod tests {
 | 
			
		||||
        let info = MyStruct::type_info();
 | 
			
		||||
        if let TypeInfo::Struct(info) = info {
 | 
			
		||||
            assert!(info.is::<MyStruct>());
 | 
			
		||||
            assert_eq!(std::any::type_name::<MyStruct>(), info.type_name());
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                std::any::type_name::<i32>(),
 | 
			
		||||
                info.field("foo").unwrap().type_name()
 | 
			
		||||
            );
 | 
			
		||||
            assert_eq!(MyStruct::type_path(), info.type_path());
 | 
			
		||||
            assert_eq!(i32::type_path(), info.field("foo").unwrap().type_path());
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                std::any::TypeId::of::<i32>(),
 | 
			
		||||
                info.field("foo").unwrap().type_id()
 | 
			
		||||
            );
 | 
			
		||||
            assert!(info.field("foo").unwrap().is::<i32>());
 | 
			
		||||
            assert_eq!("foo", info.field("foo").unwrap().name());
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                std::any::type_name::<usize>(),
 | 
			
		||||
                info.field_at(1).unwrap().type_name()
 | 
			
		||||
            );
 | 
			
		||||
            assert_eq!(usize::type_path(), info.field_at(1).unwrap().type_path());
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("Expected `TypeInfo::Struct`");
 | 
			
		||||
        }
 | 
			
		||||
@ -1326,19 +1324,10 @@ mod tests {
 | 
			
		||||
        let info = <MyGenericStruct<i32>>::type_info();
 | 
			
		||||
        if let TypeInfo::Struct(info) = info {
 | 
			
		||||
            assert!(info.is::<MyGenericStruct<i32>>());
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                std::any::type_name::<MyGenericStruct<i32>>(),
 | 
			
		||||
                info.type_name()
 | 
			
		||||
            );
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                std::any::type_name::<i32>(),
 | 
			
		||||
                info.field("foo").unwrap().type_name()
 | 
			
		||||
            );
 | 
			
		||||
            assert_eq!(MyGenericStruct::<i32>::type_path(), info.type_path());
 | 
			
		||||
            assert_eq!(i32::type_path(), info.field("foo").unwrap().type_path());
 | 
			
		||||
            assert_eq!("foo", info.field("foo").unwrap().name());
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                std::any::type_name::<usize>(),
 | 
			
		||||
                info.field_at(1).unwrap().type_name()
 | 
			
		||||
            );
 | 
			
		||||
            assert_eq!(usize::type_path(), info.field_at(1).unwrap().type_path());
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("Expected `TypeInfo::Struct`");
 | 
			
		||||
        }
 | 
			
		||||
@ -1357,11 +1346,8 @@ mod tests {
 | 
			
		||||
        let info = MyTupleStruct::type_info();
 | 
			
		||||
        if let TypeInfo::TupleStruct(info) = info {
 | 
			
		||||
            assert!(info.is::<MyTupleStruct>());
 | 
			
		||||
            assert_eq!(std::any::type_name::<MyTupleStruct>(), info.type_name());
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                std::any::type_name::<i32>(),
 | 
			
		||||
                info.field_at(1).unwrap().type_name()
 | 
			
		||||
            );
 | 
			
		||||
            assert_eq!(MyTupleStruct::type_path(), info.type_path());
 | 
			
		||||
            assert_eq!(i32::type_path(), info.field_at(1).unwrap().type_path());
 | 
			
		||||
            assert!(info.field_at(1).unwrap().is::<i32>());
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("Expected `TypeInfo::TupleStruct`");
 | 
			
		||||
@ -1373,11 +1359,8 @@ mod tests {
 | 
			
		||||
        let info = MyTuple::type_info();
 | 
			
		||||
        if let TypeInfo::Tuple(info) = info {
 | 
			
		||||
            assert!(info.is::<MyTuple>());
 | 
			
		||||
            assert_eq!(std::any::type_name::<MyTuple>(), info.type_name());
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                std::any::type_name::<f32>(),
 | 
			
		||||
                info.field_at(1).unwrap().type_name()
 | 
			
		||||
            );
 | 
			
		||||
            assert_eq!(MyTuple::type_path(), info.type_path());
 | 
			
		||||
            assert_eq!(f32::type_path(), info.field_at(1).unwrap().type_path());
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("Expected `TypeInfo::Tuple`");
 | 
			
		||||
        }
 | 
			
		||||
@ -1393,8 +1376,8 @@ mod tests {
 | 
			
		||||
        if let TypeInfo::List(info) = info {
 | 
			
		||||
            assert!(info.is::<MyList>());
 | 
			
		||||
            assert!(info.item_is::<usize>());
 | 
			
		||||
            assert_eq!(std::any::type_name::<MyList>(), info.type_name());
 | 
			
		||||
            assert_eq!(std::any::type_name::<usize>(), info.item_type_name());
 | 
			
		||||
            assert_eq!(MyList::type_path(), info.type_path());
 | 
			
		||||
            assert_eq!(usize::type_path(), info.item_type_path_table().path());
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("Expected `TypeInfo::List`");
 | 
			
		||||
        }
 | 
			
		||||
@ -1412,8 +1395,8 @@ mod tests {
 | 
			
		||||
            if let TypeInfo::List(info) = info {
 | 
			
		||||
                assert!(info.is::<MySmallVec>());
 | 
			
		||||
                assert!(info.item_is::<String>());
 | 
			
		||||
                assert_eq!(std::any::type_name::<MySmallVec>(), info.type_name());
 | 
			
		||||
                assert_eq!(std::any::type_name::<String>(), info.item_type_name());
 | 
			
		||||
                assert_eq!(MySmallVec::type_path(), info.type_path());
 | 
			
		||||
                assert_eq!(String::type_path(), info.item_type_path_table().path());
 | 
			
		||||
            } else {
 | 
			
		||||
                panic!("Expected `TypeInfo::List`");
 | 
			
		||||
            }
 | 
			
		||||
@ -1431,8 +1414,8 @@ mod tests {
 | 
			
		||||
        if let TypeInfo::Array(info) = info {
 | 
			
		||||
            assert!(info.is::<MyArray>());
 | 
			
		||||
            assert!(info.item_is::<usize>());
 | 
			
		||||
            assert_eq!(std::any::type_name::<MyArray>(), info.type_name());
 | 
			
		||||
            assert_eq!(std::any::type_name::<usize>(), info.item_type_name());
 | 
			
		||||
            assert_eq!(MyArray::type_path(), info.type_path());
 | 
			
		||||
            assert_eq!(usize::type_path(), info.item_type_path_table().path());
 | 
			
		||||
            assert_eq!(3, info.capacity());
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("Expected `TypeInfo::Array`");
 | 
			
		||||
@ -1448,7 +1431,7 @@ mod tests {
 | 
			
		||||
        let info = MyCowStr::type_info();
 | 
			
		||||
        if let TypeInfo::Value(info) = info {
 | 
			
		||||
            assert!(info.is::<MyCowStr>());
 | 
			
		||||
            assert_eq!(std::any::type_name::<MyCowStr>(), info.type_name());
 | 
			
		||||
            assert_eq!(std::any::type_name::<MyCowStr>(), info.type_path());
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("Expected `TypeInfo::Value`");
 | 
			
		||||
        }
 | 
			
		||||
@ -1464,8 +1447,11 @@ mod tests {
 | 
			
		||||
        if let TypeInfo::List(info) = info {
 | 
			
		||||
            assert!(info.is::<MyCowSlice>());
 | 
			
		||||
            assert!(info.item_is::<u8>());
 | 
			
		||||
            assert_eq!(std::any::type_name::<MyCowSlice>(), info.type_name());
 | 
			
		||||
            assert_eq!(std::any::type_name::<u8>(), info.item_type_name());
 | 
			
		||||
            assert_eq!(std::any::type_name::<MyCowSlice>(), info.type_path());
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                std::any::type_name::<u8>(),
 | 
			
		||||
                info.item_type_path_table().path()
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("Expected `TypeInfo::List`");
 | 
			
		||||
        }
 | 
			
		||||
@ -1482,9 +1468,9 @@ mod tests {
 | 
			
		||||
            assert!(info.is::<MyMap>());
 | 
			
		||||
            assert!(info.key_is::<usize>());
 | 
			
		||||
            assert!(info.value_is::<f32>());
 | 
			
		||||
            assert_eq!(std::any::type_name::<MyMap>(), info.type_name());
 | 
			
		||||
            assert_eq!(std::any::type_name::<usize>(), info.key_type_name());
 | 
			
		||||
            assert_eq!(std::any::type_name::<f32>(), info.value_type_name());
 | 
			
		||||
            assert_eq!(MyMap::type_path(), info.type_path());
 | 
			
		||||
            assert_eq!(usize::type_path(), info.key_type_path_table().path());
 | 
			
		||||
            assert_eq!(f32::type_path(), info.value_type_path_table().path());
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("Expected `TypeInfo::Map`");
 | 
			
		||||
        }
 | 
			
		||||
@ -1499,7 +1485,7 @@ mod tests {
 | 
			
		||||
        let info = MyValue::type_info();
 | 
			
		||||
        if let TypeInfo::Value(info) = info {
 | 
			
		||||
            assert!(info.is::<MyValue>());
 | 
			
		||||
            assert_eq!(std::any::type_name::<MyValue>(), info.type_name());
 | 
			
		||||
            assert_eq!(MyValue::type_path(), info.type_path());
 | 
			
		||||
        } else {
 | 
			
		||||
            panic!("Expected `TypeInfo::Value`");
 | 
			
		||||
        }
 | 
			
		||||
@ -1793,7 +1779,7 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
        let reflected: &dyn Reflect = &test;
 | 
			
		||||
        let expected = r#"
 | 
			
		||||
bevy_reflect::tests::should_reflect_debug::Test {
 | 
			
		||||
bevy_reflect::tests::Test {
 | 
			
		||||
    value: 123,
 | 
			
		||||
    list: [
 | 
			
		||||
        "A",
 | 
			
		||||
@ -1808,10 +1794,10 @@ bevy_reflect::tests::should_reflect_debug::Test {
 | 
			
		||||
    map: {
 | 
			
		||||
        123: 1.23,
 | 
			
		||||
    },
 | 
			
		||||
    a_struct: bevy_reflect::tests::should_reflect_debug::SomeStruct {
 | 
			
		||||
    a_struct: bevy_reflect::tests::SomeStruct {
 | 
			
		||||
        foo: "A Struct!",
 | 
			
		||||
    },
 | 
			
		||||
    a_tuple_struct: bevy_reflect::tests::should_reflect_debug::SomeTupleStruct(
 | 
			
		||||
    a_tuple_struct: bevy_reflect::tests::SomeTupleStruct(
 | 
			
		||||
        "A Tuple Struct!",
 | 
			
		||||
    ),
 | 
			
		||||
    enum_unit: A,
 | 
			
		||||
@ -1941,7 +1927,10 @@ bevy_reflect::tests::should_reflect_debug::Test {
 | 
			
		||||
        registry.register::<Foo<NotTypePath>>();
 | 
			
		||||
 | 
			
		||||
        let registration = registry.get(TypeId::of::<Foo<NotTypePath>>()).unwrap();
 | 
			
		||||
        assert_eq!("Foo<NotTypePath>", registration.short_name());
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            "Foo<NotTypePath>",
 | 
			
		||||
            registration.type_info().type_path_table().short_path()
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(feature = "glam")]
 | 
			
		||||
@ -1964,7 +1953,7 @@ bevy_reflect::tests::should_reflect_debug::Test {
 | 
			
		||||
            let output = to_string_pretty(&ser, config).unwrap();
 | 
			
		||||
            let expected = r#"
 | 
			
		||||
{
 | 
			
		||||
    "glam::f32::vec3::Vec3": (
 | 
			
		||||
    "glam::Vec3": (
 | 
			
		||||
        x: 12.0,
 | 
			
		||||
        y: 3.0,
 | 
			
		||||
        z: -6.9,
 | 
			
		||||
@ -1978,7 +1967,7 @@ bevy_reflect::tests::should_reflect_debug::Test {
 | 
			
		||||
        fn vec3_deserialization() {
 | 
			
		||||
            let data = r#"
 | 
			
		||||
{
 | 
			
		||||
    "glam::f32::vec3::Vec3": (
 | 
			
		||||
    "glam::Vec3": (
 | 
			
		||||
        x: 12.0,
 | 
			
		||||
        y: 3.0,
 | 
			
		||||
        z: -6.9,
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ use bevy_reflect_derive::impl_type_path;
 | 
			
		||||
use crate::utility::reflect_hasher;
 | 
			
		||||
use crate::{
 | 
			
		||||
    self as bevy_reflect, FromReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo,
 | 
			
		||||
    TypePath, TypePathTable,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// A trait used to power [list-like] operations via [reflection].
 | 
			
		||||
@ -108,9 +109,9 @@ pub trait List: Reflect {
 | 
			
		||||
/// A container for compile-time list info.
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct ListInfo {
 | 
			
		||||
    type_name: &'static str,
 | 
			
		||||
    type_path: TypePathTable,
 | 
			
		||||
    type_id: TypeId,
 | 
			
		||||
    item_type_name: &'static str,
 | 
			
		||||
    item_type_path: TypePathTable,
 | 
			
		||||
    item_type_id: TypeId,
 | 
			
		||||
    #[cfg(feature = "documentation")]
 | 
			
		||||
    docs: Option<&'static str>,
 | 
			
		||||
@ -118,11 +119,11 @@ pub struct ListInfo {
 | 
			
		||||
 | 
			
		||||
impl ListInfo {
 | 
			
		||||
    /// Create a new [`ListInfo`].
 | 
			
		||||
    pub fn new<TList: List, TItem: FromReflect>() -> Self {
 | 
			
		||||
    pub fn new<TList: List + TypePath, TItem: FromReflect + TypePath>() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            type_name: std::any::type_name::<TList>(),
 | 
			
		||||
            type_path: TypePathTable::of::<TList>(),
 | 
			
		||||
            type_id: TypeId::of::<TList>(),
 | 
			
		||||
            item_type_name: std::any::type_name::<TItem>(),
 | 
			
		||||
            item_type_path: TypePathTable::of::<TItem>(),
 | 
			
		||||
            item_type_id: TypeId::of::<TItem>(),
 | 
			
		||||
            #[cfg(feature = "documentation")]
 | 
			
		||||
            docs: None,
 | 
			
		||||
@ -135,11 +136,21 @@ impl ListInfo {
 | 
			
		||||
        Self { docs, ..self }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the list.
 | 
			
		||||
    /// A representation of the type path of the list.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn type_name(&self) -> &'static str {
 | 
			
		||||
        self.type_name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [stable, full type path] of the list.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// [stable, full type path]: TypePath
 | 
			
		||||
    /// [`type_path_table`]: Self::type_path_table
 | 
			
		||||
    pub fn type_path(&self) -> &'static str {
 | 
			
		||||
        self.type_path_table().path()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the list.
 | 
			
		||||
@ -152,11 +163,11 @@ impl ListInfo {
 | 
			
		||||
        TypeId::of::<T>() == self.type_id
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the list item.
 | 
			
		||||
    /// A representation of the type path of the list item.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn item_type_name(&self) -> &'static str {
 | 
			
		||||
        self.item_type_name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn item_type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.item_type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the list item.
 | 
			
		||||
@ -263,13 +274,6 @@ impl List for DynamicList {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Reflect for DynamicList {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
            .map(|info| info.type_name())
 | 
			
		||||
            .unwrap_or_else(|| std::any::type_name::<Self>())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,10 @@ use std::hash::Hash;
 | 
			
		||||
use bevy_reflect_derive::impl_type_path;
 | 
			
		||||
use bevy_utils::{Entry, HashMap};
 | 
			
		||||
 | 
			
		||||
use crate::{self as bevy_reflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo};
 | 
			
		||||
use crate::{
 | 
			
		||||
    self as bevy_reflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath,
 | 
			
		||||
    TypePathTable,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// A trait used to power [map-like] operations via [reflection].
 | 
			
		||||
///
 | 
			
		||||
@ -93,11 +96,11 @@ pub trait Map: Reflect {
 | 
			
		||||
/// A container for compile-time map info.
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct MapInfo {
 | 
			
		||||
    type_name: &'static str,
 | 
			
		||||
    type_path: TypePathTable,
 | 
			
		||||
    type_id: TypeId,
 | 
			
		||||
    key_type_name: &'static str,
 | 
			
		||||
    key_type_path: TypePathTable,
 | 
			
		||||
    key_type_id: TypeId,
 | 
			
		||||
    value_type_name: &'static str,
 | 
			
		||||
    value_type_path: TypePathTable,
 | 
			
		||||
    value_type_id: TypeId,
 | 
			
		||||
    #[cfg(feature = "documentation")]
 | 
			
		||||
    docs: Option<&'static str>,
 | 
			
		||||
@ -105,13 +108,17 @@ pub struct MapInfo {
 | 
			
		||||
 | 
			
		||||
impl MapInfo {
 | 
			
		||||
    /// Create a new [`MapInfo`].
 | 
			
		||||
    pub fn new<TMap: Map, TKey: Hash + Reflect, TValue: Reflect>() -> Self {
 | 
			
		||||
    pub fn new<
 | 
			
		||||
        TMap: Map + TypePath,
 | 
			
		||||
        TKey: Hash + Reflect + TypePath,
 | 
			
		||||
        TValue: Reflect + TypePath,
 | 
			
		||||
    >() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            type_name: std::any::type_name::<TMap>(),
 | 
			
		||||
            type_path: TypePathTable::of::<TMap>(),
 | 
			
		||||
            type_id: TypeId::of::<TMap>(),
 | 
			
		||||
            key_type_name: std::any::type_name::<TKey>(),
 | 
			
		||||
            key_type_path: TypePathTable::of::<TKey>(),
 | 
			
		||||
            key_type_id: TypeId::of::<TKey>(),
 | 
			
		||||
            value_type_name: std::any::type_name::<TValue>(),
 | 
			
		||||
            value_type_path: TypePathTable::of::<TValue>(),
 | 
			
		||||
            value_type_id: TypeId::of::<TValue>(),
 | 
			
		||||
            #[cfg(feature = "documentation")]
 | 
			
		||||
            docs: None,
 | 
			
		||||
@ -124,11 +131,21 @@ impl MapInfo {
 | 
			
		||||
        Self { docs, ..self }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the map.
 | 
			
		||||
    /// A representation of the type path of the map.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn type_name(&self) -> &'static str {
 | 
			
		||||
        self.type_name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [stable, full type path] of the map.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// [stable, full type path]: TypePath
 | 
			
		||||
    /// [`type_path_table`]: Self::type_path_table
 | 
			
		||||
    pub fn type_path(&self) -> &'static str {
 | 
			
		||||
        self.type_path_table().path()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the map.
 | 
			
		||||
@ -141,11 +158,11 @@ impl MapInfo {
 | 
			
		||||
        TypeId::of::<T>() == self.type_id
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the key.
 | 
			
		||||
    /// A representation of the type path of the key type.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn key_type_name(&self) -> &'static str {
 | 
			
		||||
        self.key_type_name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn key_type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.key_type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the key.
 | 
			
		||||
@ -158,11 +175,11 @@ impl MapInfo {
 | 
			
		||||
        TypeId::of::<T>() == self.key_type_id
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the value.
 | 
			
		||||
    /// A representation of the type path of the value type.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn value_type_name(&self) -> &'static str {
 | 
			
		||||
        self.value_type_name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn value_type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.value_type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the value.
 | 
			
		||||
@ -297,12 +314,6 @@ impl Map for DynamicMap {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Reflect for DynamicMap {
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
            .map(|info| info.type_name())
 | 
			
		||||
            .unwrap_or_else(|| std::any::type_name::<Self>())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,10 @@
 | 
			
		||||
use crate::{
 | 
			
		||||
    array_debug, enum_debug, list_debug, map_debug, serde::Serializable, struct_debug, tuple_debug,
 | 
			
		||||
    tuple_struct_debug, Array, DynamicTypePath, Enum, List, Map, Struct, Tuple, TupleStruct,
 | 
			
		||||
    TypeInfo, Typed, ValueInfo,
 | 
			
		||||
    TypeInfo, TypePath, Typed, ValueInfo,
 | 
			
		||||
};
 | 
			
		||||
use std::{
 | 
			
		||||
    any::{self, Any, TypeId},
 | 
			
		||||
    any::{Any, TypeId},
 | 
			
		||||
    fmt::Debug,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -73,8 +73,23 @@ pub enum ReflectOwned {
 | 
			
		||||
/// [derive macro]: bevy_reflect_derive::Reflect
 | 
			
		||||
/// [crate-level documentation]: crate
 | 
			
		||||
pub trait Reflect: DynamicTypePath + Any + Send + Sync {
 | 
			
		||||
    /// Returns the [type name][std::any::type_name] of the underlying type.
 | 
			
		||||
    fn type_name(&self) -> &str;
 | 
			
		||||
    /// Returns the type path of the underlying type.
 | 
			
		||||
    ///
 | 
			
		||||
    /// This type path will either be found through [`get_represented_type_info`]
 | 
			
		||||
    /// or taken from a [`TypePath`] implementation if the former isn't available.
 | 
			
		||||
    ///
 | 
			
		||||
    /// This method is deprecated; please consider migrating to one of the above methods.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [`get_represented_type_info`]: Reflect::get_represented_type_info
 | 
			
		||||
    #[deprecated(
 | 
			
		||||
        since = "0.12.0",
 | 
			
		||||
        note = "view the method documentation to find alternatives to this method."
 | 
			
		||||
    )]
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        self.get_represented_type_info()
 | 
			
		||||
            .map(|info| info.type_path())
 | 
			
		||||
            .unwrap_or_else(|| self.reflect_type_path())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns the [`TypeInfo`] of the type _represented_ by this value.
 | 
			
		||||
    ///
 | 
			
		||||
@ -200,10 +215,10 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync {
 | 
			
		||||
    /// Debug formatter for the value.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Any value that is not an implementor of other `Reflect` subtraits
 | 
			
		||||
    /// (e.g. [`List`], [`Map`]), will default to the format: `"Reflect(type_name)"`,
 | 
			
		||||
    /// where `type_name` is the [type name] of the underlying type.
 | 
			
		||||
    /// (e.g. [`List`], [`Map`]), will default to the format: `"Reflect(type_path)"`,
 | 
			
		||||
    /// where `type_path` is the [type path] of the underlying type.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: Self::type_name
 | 
			
		||||
    /// [type path]: TypePath::type_path
 | 
			
		||||
    fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
        match self.reflect_ref() {
 | 
			
		||||
            ReflectRef::Struct(dyn_struct) => struct_debug(dyn_struct, f),
 | 
			
		||||
@ -213,7 +228,7 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync {
 | 
			
		||||
            ReflectRef::Array(dyn_array) => array_debug(dyn_array, f),
 | 
			
		||||
            ReflectRef::Map(dyn_map) => map_debug(dyn_map, f),
 | 
			
		||||
            ReflectRef::Enum(dyn_enum) => enum_debug(dyn_enum, f),
 | 
			
		||||
            _ => write!(f, "Reflect({})", self.type_name()),
 | 
			
		||||
            _ => write!(f, "Reflect({})", self.reflect_type_path()),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -254,6 +269,19 @@ impl Typed for dyn Reflect {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// The following implementation never actually shadows the concrete TypePath implementation.
 | 
			
		||||
 | 
			
		||||
// See this playground (https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=589064053f27bc100d90da89c6a860aa).
 | 
			
		||||
impl TypePath for dyn Reflect {
 | 
			
		||||
    fn type_path() -> &'static str {
 | 
			
		||||
        "dyn bevy_reflect::Reflect"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn short_type_path() -> &'static str {
 | 
			
		||||
        "dyn Reflect"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[deny(rustdoc::broken_intra_doc_links)]
 | 
			
		||||
impl dyn Reflect {
 | 
			
		||||
    /// Downcasts the value to type `T`, consuming the trait object.
 | 
			
		||||
@ -279,8 +307,10 @@ impl dyn Reflect {
 | 
			
		||||
    ///
 | 
			
		||||
    /// Read `is` for more information on underlying values and represented types.
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn represents<T: Reflect>(&self) -> bool {
 | 
			
		||||
        self.type_name() == any::type_name::<T>()
 | 
			
		||||
    pub fn represents<T: Reflect + TypePath>(&self) -> bool {
 | 
			
		||||
        self.get_represented_type_info()
 | 
			
		||||
            .map(|t| t.type_path() == T::type_path())
 | 
			
		||||
            .unwrap_or(false)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns `true` if the underlying value is of type `T`, or `false`
 | 
			
		||||
 | 
			
		||||
@ -25,13 +25,13 @@ pub trait DeserializeValue {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
trait StructLikeInfo {
 | 
			
		||||
    fn get_name(&self) -> &str;
 | 
			
		||||
    fn get_path(&self) -> &str;
 | 
			
		||||
    fn get_field(&self, name: &str) -> Option<&NamedField>;
 | 
			
		||||
    fn iter_fields(&self) -> Iter<'_, NamedField>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
trait TupleLikeInfo {
 | 
			
		||||
    fn get_name(&self) -> &str;
 | 
			
		||||
    fn get_path(&self) -> &str;
 | 
			
		||||
    fn get_field(&self, index: usize) -> Option<&UnnamedField>;
 | 
			
		||||
    fn get_field_len(&self) -> usize;
 | 
			
		||||
}
 | 
			
		||||
@ -45,8 +45,8 @@ trait Container {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl StructLikeInfo for StructInfo {
 | 
			
		||||
    fn get_name(&self) -> &str {
 | 
			
		||||
        self.type_name()
 | 
			
		||||
    fn get_path(&self) -> &str {
 | 
			
		||||
        self.type_path()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_field(&self, name: &str) -> Option<&NamedField> {
 | 
			
		||||
@ -68,15 +68,15 @@ impl Container for StructInfo {
 | 
			
		||||
            de::Error::custom(format_args!(
 | 
			
		||||
                "no field at index {} on struct {}",
 | 
			
		||||
                index,
 | 
			
		||||
                self.type_name(),
 | 
			
		||||
                self.type_path(),
 | 
			
		||||
            ))
 | 
			
		||||
        })?;
 | 
			
		||||
        get_registration(field.type_id(), field.type_name(), registry)
 | 
			
		||||
        get_registration(field.type_id(), field.type_path(), registry)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl StructLikeInfo for StructVariantInfo {
 | 
			
		||||
    fn get_name(&self) -> &str {
 | 
			
		||||
    fn get_path(&self) -> &str {
 | 
			
		||||
        self.name()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -102,13 +102,13 @@ impl Container for StructVariantInfo {
 | 
			
		||||
                self.name(),
 | 
			
		||||
            ))
 | 
			
		||||
        })?;
 | 
			
		||||
        get_registration(field.type_id(), field.type_name(), registry)
 | 
			
		||||
        get_registration(field.type_id(), field.type_path(), registry)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TupleLikeInfo for TupleInfo {
 | 
			
		||||
    fn get_name(&self) -> &str {
 | 
			
		||||
        self.type_name()
 | 
			
		||||
    fn get_path(&self) -> &str {
 | 
			
		||||
        self.type_path()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_field(&self, index: usize) -> Option<&UnnamedField> {
 | 
			
		||||
@ -121,7 +121,7 @@ impl TupleLikeInfo for TupleInfo {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TupleLikeInfo for TupleVariantInfo {
 | 
			
		||||
    fn get_name(&self) -> &str {
 | 
			
		||||
    fn get_path(&self) -> &str {
 | 
			
		||||
        self.name()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -224,7 +224,7 @@ impl<'de> Visitor<'de> for U32Visitor {
 | 
			
		||||
///
 | 
			
		||||
/// Because the type isn't known ahead of time, the serialized data must take the form of
 | 
			
		||||
/// a map containing the following entries (in order):
 | 
			
		||||
/// 1. `type`: The _full_ [type name]
 | 
			
		||||
/// 1. `type`: The _full_ [type path]
 | 
			
		||||
/// 2. `value`: The serialized value of the reflected type
 | 
			
		||||
///
 | 
			
		||||
/// If the type is already known and the [`TypeInfo`] for it can be retrieved,
 | 
			
		||||
@ -234,7 +234,7 @@ impl<'de> Visitor<'de> for U32Visitor {
 | 
			
		||||
/// [`DynamicStruct`]: crate::DynamicStruct
 | 
			
		||||
/// [`DynamicList`]: crate::DynamicList
 | 
			
		||||
/// [`FromReflect`]: crate::FromReflect
 | 
			
		||||
/// [type name]: std::any::type_name
 | 
			
		||||
/// [type path]: crate::TypePath::type_path
 | 
			
		||||
pub struct UntypedReflectDeserializer<'a> {
 | 
			
		||||
    registry: &'a TypeRegistry,
 | 
			
		||||
}
 | 
			
		||||
@ -261,11 +261,11 @@ impl<'a, 'de> DeserializeSeed<'de> for UntypedReflectDeserializer<'a> {
 | 
			
		||||
/// A deserializer for type registrations.
 | 
			
		||||
///
 | 
			
		||||
/// This will return a [`&TypeRegistration`] corresponding to the given type.
 | 
			
		||||
/// This deserializer expects a string containing the _full_ [type name] of the
 | 
			
		||||
/// This deserializer expects a string containing the _full_ [type path] of the
 | 
			
		||||
/// type to find the `TypeRegistration` of.
 | 
			
		||||
///
 | 
			
		||||
/// [`&TypeRegistration`]: crate::TypeRegistration
 | 
			
		||||
/// [type name]: std::any::type_name
 | 
			
		||||
/// [type path]: crate::TypePath::type_path
 | 
			
		||||
pub struct TypeRegistrationDeserializer<'a> {
 | 
			
		||||
    registry: &'a TypeRegistry,
 | 
			
		||||
}
 | 
			
		||||
@ -292,12 +292,12 @@ impl<'a, 'de> DeserializeSeed<'de> for TypeRegistrationDeserializer<'a> {
 | 
			
		||||
                formatter.write_str("string containing `type` entry for the reflected value")
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            fn visit_str<E>(self, type_name: &str) -> Result<Self::Value, E>
 | 
			
		||||
            fn visit_str<E>(self, type_path: &str) -> Result<Self::Value, E>
 | 
			
		||||
            where
 | 
			
		||||
                E: Error,
 | 
			
		||||
            {
 | 
			
		||||
                self.0.get_with_name(type_name).ok_or_else(|| {
 | 
			
		||||
                    Error::custom(format_args!("No registration found for `{type_name}`"))
 | 
			
		||||
                self.0.get_with_type_path(type_path).ok_or_else(|| {
 | 
			
		||||
                    Error::custom(format_args!("No registration found for `{type_path}`"))
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -377,7 +377,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
 | 
			
		||||
    where
 | 
			
		||||
        D: serde::Deserializer<'de>,
 | 
			
		||||
    {
 | 
			
		||||
        let type_name = self.registration.type_name();
 | 
			
		||||
        let type_path = self.registration.type_info().type_path();
 | 
			
		||||
 | 
			
		||||
        // Handle both Value case and types that have a custom `ReflectDeserialize`
 | 
			
		||||
        if let Some(deserialize_reflect) = self.registration.data::<ReflectDeserialize>() {
 | 
			
		||||
@ -388,7 +388,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
 | 
			
		||||
        match self.registration.type_info() {
 | 
			
		||||
            TypeInfo::Struct(struct_info) => {
 | 
			
		||||
                let mut dynamic_struct = deserializer.deserialize_struct(
 | 
			
		||||
                    struct_info.name(),
 | 
			
		||||
                    struct_info.type_path_table().ident().unwrap(),
 | 
			
		||||
                    struct_info.field_names(),
 | 
			
		||||
                    StructVisitor {
 | 
			
		||||
                        struct_info,
 | 
			
		||||
@ -401,7 +401,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
 | 
			
		||||
            }
 | 
			
		||||
            TypeInfo::TupleStruct(tuple_struct_info) => {
 | 
			
		||||
                let mut dynamic_tuple_struct = deserializer.deserialize_tuple_struct(
 | 
			
		||||
                    tuple_struct_info.name(),
 | 
			
		||||
                    tuple_struct_info.type_path_table().ident().unwrap(),
 | 
			
		||||
                    tuple_struct_info.field_len(),
 | 
			
		||||
                    TupleStructVisitor {
 | 
			
		||||
                        tuple_struct_info,
 | 
			
		||||
@ -451,15 +451,17 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
 | 
			
		||||
                Ok(Box::new(dynamic_tuple))
 | 
			
		||||
            }
 | 
			
		||||
            TypeInfo::Enum(enum_info) => {
 | 
			
		||||
                let type_name = enum_info.type_name();
 | 
			
		||||
                let mut dynamic_enum = if type_name.starts_with("core::option::Option") {
 | 
			
		||||
                let mut dynamic_enum = if enum_info.type_path_table().module_path()
 | 
			
		||||
                    == Some("core::option")
 | 
			
		||||
                    && enum_info.type_path_table().ident() == Some("Option")
 | 
			
		||||
                {
 | 
			
		||||
                    deserializer.deserialize_option(OptionVisitor {
 | 
			
		||||
                        enum_info,
 | 
			
		||||
                        registry: self.registry,
 | 
			
		||||
                    })?
 | 
			
		||||
                } else {
 | 
			
		||||
                    deserializer.deserialize_enum(
 | 
			
		||||
                        enum_info.name(),
 | 
			
		||||
                        enum_info.type_path_table().ident().unwrap(),
 | 
			
		||||
                        enum_info.variant_names(),
 | 
			
		||||
                        EnumVisitor {
 | 
			
		||||
                            enum_info,
 | 
			
		||||
@ -474,7 +476,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
 | 
			
		||||
            TypeInfo::Value(_) => {
 | 
			
		||||
                // This case should already be handled
 | 
			
		||||
                Err(de::Error::custom(format_args!(
 | 
			
		||||
                    "the TypeRegistration for {type_name} doesn't have ReflectDeserialize",
 | 
			
		||||
                    "the TypeRegistration for {type_path} doesn't have ReflectDeserialize",
 | 
			
		||||
                )))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -578,10 +580,10 @@ impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> {
 | 
			
		||||
                de::Error::custom(format_args!(
 | 
			
		||||
                    "no field at index {} on tuple {}",
 | 
			
		||||
                    index,
 | 
			
		||||
                    self.tuple_struct_info.type_name(),
 | 
			
		||||
                    self.tuple_struct_info.type_path(),
 | 
			
		||||
                ))
 | 
			
		||||
            })?;
 | 
			
		||||
            get_registration(field.type_id(), field.type_name(), self.registry)
 | 
			
		||||
            get_registration(field.type_id(), field.type_path(), self.registry)
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        while let Some(value) = seq.next_element_seed(TypedReflectDeserializer {
 | 
			
		||||
@ -650,7 +652,7 @@ impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> {
 | 
			
		||||
        let mut vec = Vec::with_capacity(seq.size_hint().unwrap_or_default());
 | 
			
		||||
        let registration = get_registration(
 | 
			
		||||
            self.array_info.item_type_id(),
 | 
			
		||||
            self.array_info.item_type_name(),
 | 
			
		||||
            self.array_info.item_type_path_table().path(),
 | 
			
		||||
            self.registry,
 | 
			
		||||
        )?;
 | 
			
		||||
        while let Some(value) = seq.next_element_seed(TypedReflectDeserializer {
 | 
			
		||||
@ -690,7 +692,7 @@ impl<'a, 'de> Visitor<'de> for ListVisitor<'a> {
 | 
			
		||||
        let mut list = DynamicList::default();
 | 
			
		||||
        let registration = get_registration(
 | 
			
		||||
            self.list_info.item_type_id(),
 | 
			
		||||
            self.list_info.item_type_name(),
 | 
			
		||||
            self.list_info.item_type_path_table().path(),
 | 
			
		||||
            self.registry,
 | 
			
		||||
        )?;
 | 
			
		||||
        while let Some(value) = seq.next_element_seed(TypedReflectDeserializer {
 | 
			
		||||
@ -722,12 +724,12 @@ impl<'a, 'de> Visitor<'de> for MapVisitor<'a> {
 | 
			
		||||
        let mut dynamic_map = DynamicMap::default();
 | 
			
		||||
        let key_registration = get_registration(
 | 
			
		||||
            self.map_info.key_type_id(),
 | 
			
		||||
            self.map_info.key_type_name(),
 | 
			
		||||
            self.map_info.key_type_path_table().path(),
 | 
			
		||||
            self.registry,
 | 
			
		||||
        )?;
 | 
			
		||||
        let value_registration = get_registration(
 | 
			
		||||
            self.map_info.value_type_id(),
 | 
			
		||||
            self.map_info.value_type_name(),
 | 
			
		||||
            self.map_info.value_type_path_table().path(),
 | 
			
		||||
            self.registry,
 | 
			
		||||
        )?;
 | 
			
		||||
        while let Some(key) = map.next_key_seed(TypedReflectDeserializer {
 | 
			
		||||
@ -782,7 +784,7 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> {
 | 
			
		||||
            VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => {
 | 
			
		||||
                let field = tuple_info.field_at(0).unwrap();
 | 
			
		||||
                let registration =
 | 
			
		||||
                    get_registration(field.type_id(), field.type_name(), self.registry)?;
 | 
			
		||||
                    get_registration(field.type_id(), field.type_path(), self.registry)?;
 | 
			
		||||
                let value = variant.newtype_variant_seed(TypedReflectDeserializer {
 | 
			
		||||
                    registration,
 | 
			
		||||
                    registry: self.registry,
 | 
			
		||||
@ -850,7 +852,7 @@ impl<'de> DeserializeSeed<'de> for VariantDeserializer {
 | 
			
		||||
                    Error::custom(format_args!(
 | 
			
		||||
                        "no variant found at index `{}` on enum `{}`",
 | 
			
		||||
                        variant_index,
 | 
			
		||||
                        self.0.name()
 | 
			
		||||
                        self.0.type_path()
 | 
			
		||||
                    ))
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
@ -960,7 +962,7 @@ impl<'a, 'de> Visitor<'de> for OptionVisitor<'a> {
 | 
			
		||||
 | 
			
		||||
    fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
 | 
			
		||||
        formatter.write_str("reflected option value of type ")?;
 | 
			
		||||
        formatter.write_str(self.enum_info.type_name())
 | 
			
		||||
        formatter.write_str(self.enum_info.type_path())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
 | 
			
		||||
@ -972,7 +974,7 @@ impl<'a, 'de> Visitor<'de> for OptionVisitor<'a> {
 | 
			
		||||
            VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => {
 | 
			
		||||
                let field = tuple_info.field_at(0).unwrap();
 | 
			
		||||
                let registration =
 | 
			
		||||
                    get_registration(field.type_id(), field.type_name(), self.registry)?;
 | 
			
		||||
                    get_registration(field.type_id(), field.type_path(), self.registry)?;
 | 
			
		||||
                let de = TypedReflectDeserializer {
 | 
			
		||||
                    registration,
 | 
			
		||||
                    registry: self.registry,
 | 
			
		||||
@ -1019,7 +1021,7 @@ where
 | 
			
		||||
                ExpectedValues(fields.collect())
 | 
			
		||||
            ))
 | 
			
		||||
        })?;
 | 
			
		||||
        let registration = get_registration(field.type_id(), field.type_name(), registry)?;
 | 
			
		||||
        let registration = get_registration(field.type_id(), field.type_path(), registry)?;
 | 
			
		||||
        let value = map.next_value_seed(TypedReflectDeserializer {
 | 
			
		||||
            registration,
 | 
			
		||||
            registry,
 | 
			
		||||
@ -1046,7 +1048,7 @@ where
 | 
			
		||||
        let field = info.get_field(index).ok_or_else(|| {
 | 
			
		||||
            Error::invalid_length(index, &info.get_field_len().to_string().as_str())
 | 
			
		||||
        })?;
 | 
			
		||||
        get_registration(field.type_id(), field.type_name(), registry)
 | 
			
		||||
        get_registration(field.type_id(), field.type_path(), registry)
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    while let Some(value) = seq.next_element_seed(TypedReflectDeserializer {
 | 
			
		||||
@ -1074,11 +1076,11 @@ where
 | 
			
		||||
 | 
			
		||||
fn get_registration<'a, E: Error>(
 | 
			
		||||
    type_id: TypeId,
 | 
			
		||||
    type_name: &str,
 | 
			
		||||
    type_path: &str,
 | 
			
		||||
    registry: &'a TypeRegistry,
 | 
			
		||||
) -> Result<&'a TypeRegistration, E> {
 | 
			
		||||
    let registration = registry.get(type_id).ok_or_else(|| {
 | 
			
		||||
        Error::custom(format_args!("no registration found for type `{type_name}`"))
 | 
			
		||||
        Error::custom(format_args!("no registration found for type `{type_path}`"))
 | 
			
		||||
    })?;
 | 
			
		||||
    Ok(registration)
 | 
			
		||||
}
 | 
			
		||||
@ -1356,7 +1358,7 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
        // === Normal === //
 | 
			
		||||
        let input = r#"{
 | 
			
		||||
            "bevy_reflect::serde::de::tests::should_deserialize_option::OptionTest": (
 | 
			
		||||
            "bevy_reflect::serde::de::tests::OptionTest": (
 | 
			
		||||
                none: None,
 | 
			
		||||
                simple: Some("Hello world!"),
 | 
			
		||||
                complex: Some((
 | 
			
		||||
@ -1378,7 +1380,7 @@ mod tests {
 | 
			
		||||
        let input = r#"
 | 
			
		||||
        #![enable(implicit_some)]
 | 
			
		||||
        {
 | 
			
		||||
            "bevy_reflect::serde::de::tests::should_deserialize_option::OptionTest": (
 | 
			
		||||
            "bevy_reflect::serde::de::tests::OptionTest": (
 | 
			
		||||
                none: None,
 | 
			
		||||
                simple: "Hello world!",
 | 
			
		||||
                complex: (
 | 
			
		||||
@ -1415,7 +1417,7 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
        // === Unit Variant === //
 | 
			
		||||
        let input = r#"{
 | 
			
		||||
    "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": Unit,
 | 
			
		||||
    "bevy_reflect::serde::de::tests::MyEnum": Unit,
 | 
			
		||||
}"#;
 | 
			
		||||
        let reflect_deserializer = UntypedReflectDeserializer::new(®istry);
 | 
			
		||||
        let mut deserializer = ron::de::Deserializer::from_str(input).unwrap();
 | 
			
		||||
@ -1426,7 +1428,7 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
        // === NewType Variant === //
 | 
			
		||||
        let input = r#"{
 | 
			
		||||
    "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": NewType(123),
 | 
			
		||||
    "bevy_reflect::serde::de::tests::MyEnum": NewType(123),
 | 
			
		||||
}"#;
 | 
			
		||||
        let reflect_deserializer = UntypedReflectDeserializer::new(®istry);
 | 
			
		||||
        let mut deserializer = ron::de::Deserializer::from_str(input).unwrap();
 | 
			
		||||
@ -1437,7 +1439,7 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
        // === Tuple Variant === //
 | 
			
		||||
        let input = r#"{
 | 
			
		||||
    "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": Tuple(1.23, 3.21),
 | 
			
		||||
    "bevy_reflect::serde::de::tests::MyEnum": Tuple(1.23, 3.21),
 | 
			
		||||
}"#;
 | 
			
		||||
        let reflect_deserializer = UntypedReflectDeserializer::new(®istry);
 | 
			
		||||
        let mut deserializer = ron::de::Deserializer::from_str(input).unwrap();
 | 
			
		||||
@ -1448,7 +1450,7 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
        // === Struct Variant === //
 | 
			
		||||
        let input = r#"{
 | 
			
		||||
    "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": Struct(
 | 
			
		||||
    "bevy_reflect::serde::de::tests::MyEnum": Struct(
 | 
			
		||||
        value: "I <3 Enums",
 | 
			
		||||
    ),
 | 
			
		||||
}"#;
 | 
			
		||||
 | 
			
		||||
@ -94,7 +94,7 @@ mod tests {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    #[should_panic(expected = "cannot get type info for bevy_reflect::struct_trait::DynamicStruct")]
 | 
			
		||||
    #[should_panic(expected = "cannot get type info for bevy_reflect::DynamicStruct")]
 | 
			
		||||
    fn unproxied_dynamic_should_not_serialize() {
 | 
			
		||||
        let registry = TypeRegistry::default();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,7 @@ fn get_serializable<'a, E: serde::ser::Error>(
 | 
			
		||||
        .ok_or_else(|| {
 | 
			
		||||
            serde::ser::Error::custom(format_args!(
 | 
			
		||||
                "Type '{}' did not register ReflectSerialize",
 | 
			
		||||
                reflect_value.type_name()
 | 
			
		||||
                reflect_value.reflect_type_path()
 | 
			
		||||
            ))
 | 
			
		||||
        })?;
 | 
			
		||||
    Ok(reflect_serialize.get_serializable(reflect_value))
 | 
			
		||||
@ -46,10 +46,10 @@ fn get_serializable<'a, E: serde::ser::Error>(
 | 
			
		||||
/// A general purpose serializer for reflected types.
 | 
			
		||||
///
 | 
			
		||||
/// The serialized data will take the form of a map containing the following entries:
 | 
			
		||||
/// 1. `type`: The _full_ [type name]
 | 
			
		||||
/// 1. `type`: The _full_ [type path]
 | 
			
		||||
/// 2. `value`: The serialized value of the reflected type
 | 
			
		||||
///
 | 
			
		||||
/// [type name]: std::any::type_name
 | 
			
		||||
/// [type path]: crate::TypePath::type_path
 | 
			
		||||
pub struct ReflectSerializer<'a> {
 | 
			
		||||
    pub value: &'a dyn Reflect,
 | 
			
		||||
    pub registry: &'a TypeRegistry,
 | 
			
		||||
@ -68,7 +68,7 @@ impl<'a> Serialize for ReflectSerializer<'a> {
 | 
			
		||||
    {
 | 
			
		||||
        let mut state = serializer.serialize_map(Some(1))?;
 | 
			
		||||
        state.serialize_entry(
 | 
			
		||||
            self.value.type_name(),
 | 
			
		||||
            self.value.reflect_type_path(),
 | 
			
		||||
            &TypedReflectSerializer::new(self.value, self.registry),
 | 
			
		||||
        )?;
 | 
			
		||||
        state.end()
 | 
			
		||||
@ -172,7 +172,7 @@ impl<'a> Serialize for StructSerializer<'a> {
 | 
			
		||||
            .ok_or_else(|| {
 | 
			
		||||
                Error::custom(format_args!(
 | 
			
		||||
                    "cannot get type info for {}",
 | 
			
		||||
                    self.struct_value.type_name()
 | 
			
		||||
                    self.struct_value.reflect_type_path()
 | 
			
		||||
                ))
 | 
			
		||||
            })?;
 | 
			
		||||
 | 
			
		||||
@ -191,7 +191,7 @@ impl<'a> Serialize for StructSerializer<'a> {
 | 
			
		||||
            .and_then(|registration| registration.data::<SerializationData>());
 | 
			
		||||
        let ignored_len = serialization_data.map(|data| data.len()).unwrap_or(0);
 | 
			
		||||
        let mut state = serializer.serialize_struct(
 | 
			
		||||
            struct_info.name(),
 | 
			
		||||
            struct_info.type_path_table().ident().unwrap(),
 | 
			
		||||
            self.struct_value.field_len() - ignored_len,
 | 
			
		||||
        )?;
 | 
			
		||||
 | 
			
		||||
@ -225,7 +225,7 @@ impl<'a> Serialize for TupleStructSerializer<'a> {
 | 
			
		||||
            .ok_or_else(|| {
 | 
			
		||||
                Error::custom(format_args!(
 | 
			
		||||
                    "cannot get type info for {}",
 | 
			
		||||
                    self.tuple_struct.type_name()
 | 
			
		||||
                    self.tuple_struct.reflect_type_path()
 | 
			
		||||
                ))
 | 
			
		||||
            })?;
 | 
			
		||||
 | 
			
		||||
@ -244,7 +244,7 @@ impl<'a> Serialize for TupleStructSerializer<'a> {
 | 
			
		||||
            .and_then(|registration| registration.data::<SerializationData>());
 | 
			
		||||
        let ignored_len = serialization_data.map(|data| data.len()).unwrap_or(0);
 | 
			
		||||
        let mut state = serializer.serialize_tuple_struct(
 | 
			
		||||
            tuple_struct_info.name(),
 | 
			
		||||
            tuple_struct_info.type_path_table().ident().unwrap(),
 | 
			
		||||
            self.tuple_struct.field_len() - ignored_len,
 | 
			
		||||
        )?;
 | 
			
		||||
 | 
			
		||||
@ -274,7 +274,7 @@ impl<'a> Serialize for EnumSerializer<'a> {
 | 
			
		||||
        let type_info = self.enum_value.get_represented_type_info().ok_or_else(|| {
 | 
			
		||||
            Error::custom(format_args!(
 | 
			
		||||
                "cannot get type info for {}",
 | 
			
		||||
                self.enum_value.type_name()
 | 
			
		||||
                self.enum_value.reflect_type_path()
 | 
			
		||||
            ))
 | 
			
		||||
        })?;
 | 
			
		||||
 | 
			
		||||
@ -287,7 +287,7 @@ impl<'a> Serialize for EnumSerializer<'a> {
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let enum_name = enum_info.name();
 | 
			
		||||
        let enum_name = enum_info.type_path_table().ident().unwrap();
 | 
			
		||||
        let variant_index = self.enum_value.variant_index() as u32;
 | 
			
		||||
        let variant_info = enum_info
 | 
			
		||||
            .variant_at(variant_index as usize)
 | 
			
		||||
@ -302,10 +302,8 @@ impl<'a> Serialize for EnumSerializer<'a> {
 | 
			
		||||
 | 
			
		||||
        match variant_type {
 | 
			
		||||
            VariantType::Unit => {
 | 
			
		||||
                if self
 | 
			
		||||
                    .enum_value
 | 
			
		||||
                    .type_name()
 | 
			
		||||
                    .starts_with("core::option::Option")
 | 
			
		||||
                if self.enum_value.reflect_module_path() == Some("core::option")
 | 
			
		||||
                    && self.enum_value.reflect_type_ident() == Some("Option")
 | 
			
		||||
                {
 | 
			
		||||
                    serializer.serialize_none()
 | 
			
		||||
                } else {
 | 
			
		||||
@ -341,7 +339,7 @@ impl<'a> Serialize for EnumSerializer<'a> {
 | 
			
		||||
                let field = self.enum_value.field_at(0).unwrap();
 | 
			
		||||
                if self
 | 
			
		||||
                    .enum_value
 | 
			
		||||
                    .type_name()
 | 
			
		||||
                    .reflect_type_path()
 | 
			
		||||
                    .starts_with("core::option::Option")
 | 
			
		||||
                {
 | 
			
		||||
                    serializer.serialize_some(&TypedReflectSerializer::new(field, self.registry))
 | 
			
		||||
@ -667,7 +665,7 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
        let output = ron::ser::to_string_pretty(&serializer, config).unwrap();
 | 
			
		||||
        let expected = r#"{
 | 
			
		||||
    "bevy_reflect::serde::ser::tests::should_serialize_option::OptionTest": (
 | 
			
		||||
    "bevy_reflect::serde::ser::tests::OptionTest": (
 | 
			
		||||
        none: None,
 | 
			
		||||
        simple: Some("Hello world!"),
 | 
			
		||||
        complex: Some((
 | 
			
		||||
@ -687,7 +685,7 @@ mod tests {
 | 
			
		||||
        let output = ron::ser::to_string_pretty(&serializer, config).unwrap();
 | 
			
		||||
        let expected = r#"#![enable(implicit_some)]
 | 
			
		||||
{
 | 
			
		||||
    "bevy_reflect::serde::ser::tests::should_serialize_option::OptionTest": (
 | 
			
		||||
    "bevy_reflect::serde::ser::tests::OptionTest": (
 | 
			
		||||
        none: None,
 | 
			
		||||
        simple: "Hello world!",
 | 
			
		||||
        complex: (
 | 
			
		||||
@ -719,7 +717,7 @@ mod tests {
 | 
			
		||||
        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::enum_should_serialize::MyEnum": Unit,
 | 
			
		||||
    "bevy_reflect::serde::ser::tests::MyEnum": Unit,
 | 
			
		||||
}"#;
 | 
			
		||||
        assert_eq!(expected, output);
 | 
			
		||||
 | 
			
		||||
@ -728,7 +726,7 @@ mod tests {
 | 
			
		||||
        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::enum_should_serialize::MyEnum": NewType(123),
 | 
			
		||||
    "bevy_reflect::serde::ser::tests::MyEnum": NewType(123),
 | 
			
		||||
}"#;
 | 
			
		||||
        assert_eq!(expected, output);
 | 
			
		||||
 | 
			
		||||
@ -737,7 +735,7 @@ mod tests {
 | 
			
		||||
        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::enum_should_serialize::MyEnum": Tuple(1.23, 3.21),
 | 
			
		||||
    "bevy_reflect::serde::ser::tests::MyEnum": Tuple(1.23, 3.21),
 | 
			
		||||
}"#;
 | 
			
		||||
        assert_eq!(expected, output);
 | 
			
		||||
 | 
			
		||||
@ -748,7 +746,7 @@ mod tests {
 | 
			
		||||
        let serializer = ReflectSerializer::new(&value, ®istry);
 | 
			
		||||
        let output = ron::ser::to_string_pretty(&serializer, config).unwrap();
 | 
			
		||||
        let expected = r#"{
 | 
			
		||||
    "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": Struct(
 | 
			
		||||
    "bevy_reflect::serde::ser::tests::MyEnum": Struct(
 | 
			
		||||
        value: "I <3 Enums",
 | 
			
		||||
    ),
 | 
			
		||||
}"#;
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
use crate::{
 | 
			
		||||
    self as bevy_reflect, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo,
 | 
			
		||||
    TypePath, TypePathTable,
 | 
			
		||||
};
 | 
			
		||||
use bevy_reflect_derive::impl_type_path;
 | 
			
		||||
use bevy_utils::{Entry, HashMap};
 | 
			
		||||
@ -75,8 +76,7 @@ pub trait Struct: Reflect {
 | 
			
		||||
/// A container for compile-time named struct info.
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct StructInfo {
 | 
			
		||||
    name: &'static str,
 | 
			
		||||
    type_name: &'static str,
 | 
			
		||||
    type_path: TypePathTable,
 | 
			
		||||
    type_id: TypeId,
 | 
			
		||||
    fields: Box<[NamedField]>,
 | 
			
		||||
    field_names: Box<[&'static str]>,
 | 
			
		||||
@ -90,10 +90,9 @@ impl StructInfo {
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Arguments
 | 
			
		||||
    ///
 | 
			
		||||
    /// * `name`: The name of this struct (_without_ generics or lifetimes)
 | 
			
		||||
    /// * `fields`: The fields of this struct in the order they are defined
 | 
			
		||||
    ///
 | 
			
		||||
    pub fn new<T: Reflect>(name: &'static str, fields: &[NamedField]) -> Self {
 | 
			
		||||
    pub fn new<T: Reflect + TypePath>(fields: &[NamedField]) -> Self {
 | 
			
		||||
        let field_indices = fields
 | 
			
		||||
            .iter()
 | 
			
		||||
            .enumerate()
 | 
			
		||||
@ -103,8 +102,7 @@ impl StructInfo {
 | 
			
		||||
        let field_names = fields.iter().map(|field| field.name()).collect();
 | 
			
		||||
 | 
			
		||||
        Self {
 | 
			
		||||
            name,
 | 
			
		||||
            type_name: std::any::type_name::<T>(),
 | 
			
		||||
            type_path: TypePathTable::of::<T>(),
 | 
			
		||||
            type_id: TypeId::of::<T>(),
 | 
			
		||||
            fields: fields.to_vec().into_boxed_slice(),
 | 
			
		||||
            field_names,
 | 
			
		||||
@ -152,20 +150,21 @@ impl StructInfo {
 | 
			
		||||
        self.fields.len()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The name of the struct.
 | 
			
		||||
    /// A representation of the type path of the struct.
 | 
			
		||||
    ///
 | 
			
		||||
    /// This does _not_ include any generics or lifetimes.
 | 
			
		||||
    ///
 | 
			
		||||
    /// For example, `foo::bar::Baz<'a, T>` would simply be `Baz`.
 | 
			
		||||
    pub fn name(&self) -> &'static str {
 | 
			
		||||
        self.name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the struct.
 | 
			
		||||
    /// The [stable, full type path] of the struct.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn type_name(&self) -> &'static str {
 | 
			
		||||
        self.type_name
 | 
			
		||||
    /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// [stable, full type path]: TypePath
 | 
			
		||||
    /// [`type_path_table`]: Self::type_path_table
 | 
			
		||||
    pub fn type_path(&self) -> &'static str {
 | 
			
		||||
        self.type_path_table().path()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the struct.
 | 
			
		||||
@ -392,13 +391,6 @@ impl Struct for DynamicStruct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Reflect for DynamicStruct {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
            .map(|info| info.type_name())
 | 
			
		||||
            .unwrap_or_else(|| std::any::type_name::<Self>())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
@ -551,7 +543,7 @@ pub fn struct_partial_eq<S: Struct>(a: &S, b: &dyn Reflect) -> Option<bool> {
 | 
			
		||||
/// ```
 | 
			
		||||
#[inline]
 | 
			
		||||
pub fn struct_debug(dyn_struct: &dyn Struct, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
    let mut debug = f.debug_struct(dyn_struct.type_name());
 | 
			
		||||
    let mut debug = f.debug_struct(dyn_struct.reflect_type_path());
 | 
			
		||||
    for field_index in 0..dyn_struct.field_len() {
 | 
			
		||||
        let field = dyn_struct.field_at(field_index).unwrap();
 | 
			
		||||
        debug.field(
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,13 @@
 | 
			
		||||
use bevy_reflect_derive::impl_type_path;
 | 
			
		||||
use bevy_utils::all_tuples;
 | 
			
		||||
 | 
			
		||||
use crate::TypePathTable;
 | 
			
		||||
use crate::{
 | 
			
		||||
    self as bevy_reflect, utility::GenericTypePathCell, FromReflect, GetTypeRegistration, Reflect,
 | 
			
		||||
    ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed,
 | 
			
		||||
    UnnamedField,
 | 
			
		||||
};
 | 
			
		||||
use std::any::{Any, TypeId};
 | 
			
		||||
use std::borrow::Cow;
 | 
			
		||||
use std::fmt::{Debug, Formatter};
 | 
			
		||||
use std::slice::Iter;
 | 
			
		||||
 | 
			
		||||
@ -138,7 +139,7 @@ impl GetTupleField for dyn Tuple {
 | 
			
		||||
/// A container for compile-time tuple info.
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct TupleInfo {
 | 
			
		||||
    type_name: &'static str,
 | 
			
		||||
    type_path: TypePathTable,
 | 
			
		||||
    type_id: TypeId,
 | 
			
		||||
    fields: Box<[UnnamedField]>,
 | 
			
		||||
    #[cfg(feature = "documentation")]
 | 
			
		||||
@ -152,9 +153,9 @@ impl TupleInfo {
 | 
			
		||||
    ///
 | 
			
		||||
    /// * `fields`: The fields of this tuple in the order they are defined
 | 
			
		||||
    ///
 | 
			
		||||
    pub fn new<T: Reflect>(fields: &[UnnamedField]) -> Self {
 | 
			
		||||
    pub fn new<T: Reflect + TypePath>(fields: &[UnnamedField]) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            type_name: std::any::type_name::<T>(),
 | 
			
		||||
            type_path: TypePathTable::of::<T>(),
 | 
			
		||||
            type_id: TypeId::of::<T>(),
 | 
			
		||||
            fields: fields.to_vec().into_boxed_slice(),
 | 
			
		||||
            #[cfg(feature = "documentation")]
 | 
			
		||||
@ -183,11 +184,21 @@ impl TupleInfo {
 | 
			
		||||
        self.fields.len()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the tuple.
 | 
			
		||||
    /// A representation of the type path of the tuple.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn type_name(&self) -> &'static str {
 | 
			
		||||
        self.type_name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [stable, full type path] of the tuple.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// [stable, full type path]: TypePath
 | 
			
		||||
    /// [`type_path_table`]: Self::type_path_table
 | 
			
		||||
    pub fn type_path(&self) -> &'static str {
 | 
			
		||||
        self.type_path_table().path()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the tuple.
 | 
			
		||||
@ -210,7 +221,6 @@ impl TupleInfo {
 | 
			
		||||
/// A tuple which allows fields to be added at runtime.
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct DynamicTuple {
 | 
			
		||||
    name: Cow<'static, str>,
 | 
			
		||||
    represented_type: Option<&'static TypeInfo>,
 | 
			
		||||
    fields: Vec<Box<dyn Reflect>>,
 | 
			
		||||
}
 | 
			
		||||
@ -230,8 +240,6 @@ impl DynamicTuple {
 | 
			
		||||
                "expected TypeInfo::Tuple but received: {:?}",
 | 
			
		||||
                represented_type
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            self.name = Cow::Borrowed(represented_type.type_name());
 | 
			
		||||
        }
 | 
			
		||||
        self.represented_type = represented_type;
 | 
			
		||||
    }
 | 
			
		||||
@ -240,28 +248,12 @@ impl DynamicTuple {
 | 
			
		||||
    pub fn insert_boxed(&mut self, value: Box<dyn Reflect>) {
 | 
			
		||||
        self.represented_type = None;
 | 
			
		||||
        self.fields.push(value);
 | 
			
		||||
        self.generate_name();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Appends a typed element with value `value` to the tuple.
 | 
			
		||||
    pub fn insert<T: Reflect>(&mut self, value: T) {
 | 
			
		||||
        self.represented_type = None;
 | 
			
		||||
        self.insert_boxed(Box::new(value));
 | 
			
		||||
        self.generate_name();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn generate_name(&mut self) {
 | 
			
		||||
        let mut name = self.name.to_string();
 | 
			
		||||
        name.clear();
 | 
			
		||||
        name.push('(');
 | 
			
		||||
        for (i, field) in self.fields.iter().enumerate() {
 | 
			
		||||
            if i > 0 {
 | 
			
		||||
                name.push_str(", ");
 | 
			
		||||
            }
 | 
			
		||||
            name.push_str(field.type_name());
 | 
			
		||||
        }
 | 
			
		||||
        name.push(')');
 | 
			
		||||
        self.name = Cow::Owned(name);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -297,7 +289,6 @@ impl Tuple for DynamicTuple {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn clone_dynamic(&self) -> DynamicTuple {
 | 
			
		||||
        DynamicTuple {
 | 
			
		||||
            name: self.name.clone(),
 | 
			
		||||
            represented_type: self.represented_type,
 | 
			
		||||
            fields: self
 | 
			
		||||
                .fields
 | 
			
		||||
@ -309,13 +300,6 @@ impl Tuple for DynamicTuple {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Reflect for DynamicTuple {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
            .map(|info| info.type_name())
 | 
			
		||||
            .unwrap_or_else(|| &self.name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
@ -514,7 +498,6 @@ macro_rules! impl_reflect_tuple {
 | 
			
		||||
            fn clone_dynamic(&self) -> DynamicTuple {
 | 
			
		||||
                let info = self.get_represented_type_info();
 | 
			
		||||
                DynamicTuple {
 | 
			
		||||
                    name: Cow::Borrowed(::core::any::type_name::<Self>()),
 | 
			
		||||
                    represented_type: info,
 | 
			
		||||
                    fields: self
 | 
			
		||||
                        .iter_fields()
 | 
			
		||||
@ -525,10 +508,6 @@ macro_rules! impl_reflect_tuple {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        impl<$($name: Reflect + TypePath),*> Reflect for ($($name,)*) {
 | 
			
		||||
            fn type_name(&self) -> &str {
 | 
			
		||||
                std::any::type_name::<Self>()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
                Some(<Self as Typed>::type_info())
 | 
			
		||||
            }
 | 
			
		||||
@ -600,22 +579,6 @@ macro_rules! impl_reflect_tuple {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        impl <$($name: Reflect + TypePath),*> TypePath for ($($name,)*) {
 | 
			
		||||
            fn type_path() -> &'static str {
 | 
			
		||||
                static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
                CELL.get_or_insert::<Self, _>(|| {
 | 
			
		||||
                    "(".to_owned() $(+ <$name as TypePath>::type_path())* + ")"
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            fn short_type_path() -> &'static str {
 | 
			
		||||
                static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
                CELL.get_or_insert::<Self, _>(|| {
 | 
			
		||||
                    "(".to_owned() $(+ <$name as TypePath>::short_type_path())* + ")"
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        impl<$($name: Reflect + TypePath),*> GetTypeRegistration for ($($name,)*) {
 | 
			
		||||
            fn get_type_registration() -> TypeRegistration {
 | 
			
		||||
@ -655,3 +618,56 @@ impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I}
 | 
			
		||||
impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J}
 | 
			
		||||
impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K}
 | 
			
		||||
impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K, 11: L}
 | 
			
		||||
 | 
			
		||||
macro_rules! impl_type_path_tuple {
 | 
			
		||||
    () => {
 | 
			
		||||
        impl TypePath for () {
 | 
			
		||||
            fn type_path() -> &'static str {
 | 
			
		||||
                "()"
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            fn short_type_path() -> &'static str {
 | 
			
		||||
                "()"
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ($param:ident) => {
 | 
			
		||||
        impl <$param: TypePath> TypePath for ($param,) {
 | 
			
		||||
            fn type_path() -> &'static str {
 | 
			
		||||
                static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
                CELL.get_or_insert::<Self, _>(|| {
 | 
			
		||||
                    "(".to_owned() + $param::type_path() + ",)"
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            fn short_type_path() -> &'static str {
 | 
			
		||||
                static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
                CELL.get_or_insert::<Self, _>(|| {
 | 
			
		||||
                    "(".to_owned() + $param::short_type_path() + ",)"
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ($last:ident $(,$param:ident)*) => {
 | 
			
		||||
 | 
			
		||||
        impl <$($param: TypePath,)* $last: TypePath> TypePath for ($($param,)* $last) {
 | 
			
		||||
            fn type_path() -> &'static str {
 | 
			
		||||
                static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
                CELL.get_or_insert::<Self, _>(|| {
 | 
			
		||||
                    "(".to_owned() $(+ $param::type_path() + ", ")* + $last::type_path() + ")"
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            fn short_type_path() -> &'static str {
 | 
			
		||||
                static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
                CELL.get_or_insert::<Self, _>(|| {
 | 
			
		||||
                    "(".to_owned() $(+ $param::short_type_path() + ", ")* + $last::short_type_path() + ")"
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
all_tuples!(impl_type_path_tuple, 0, 12, P);
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,8 @@
 | 
			
		||||
use bevy_reflect_derive::impl_type_path;
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    self as bevy_reflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, UnnamedField,
 | 
			
		||||
    self as bevy_reflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath,
 | 
			
		||||
    TypePathTable, UnnamedField,
 | 
			
		||||
};
 | 
			
		||||
use std::any::{Any, TypeId};
 | 
			
		||||
use std::fmt::{Debug, Formatter};
 | 
			
		||||
@ -55,8 +56,7 @@ pub trait TupleStruct: Reflect {
 | 
			
		||||
/// A container for compile-time tuple struct info.
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct TupleStructInfo {
 | 
			
		||||
    name: &'static str,
 | 
			
		||||
    type_name: &'static str,
 | 
			
		||||
    type_path: TypePathTable,
 | 
			
		||||
    type_id: TypeId,
 | 
			
		||||
    fields: Box<[UnnamedField]>,
 | 
			
		||||
    #[cfg(feature = "documentation")]
 | 
			
		||||
@ -68,13 +68,11 @@ impl TupleStructInfo {
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Arguments
 | 
			
		||||
    ///
 | 
			
		||||
    /// * `name`: The name of this struct (_without_ generics or lifetimes)
 | 
			
		||||
    /// * `fields`: The fields of this struct in the order they are defined
 | 
			
		||||
    ///
 | 
			
		||||
    pub fn new<T: Reflect>(name: &'static str, fields: &[UnnamedField]) -> Self {
 | 
			
		||||
    pub fn new<T: Reflect + TypePath>(fields: &[UnnamedField]) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            name,
 | 
			
		||||
            type_name: std::any::type_name::<T>(),
 | 
			
		||||
            type_path: TypePathTable::of::<T>(),
 | 
			
		||||
            type_id: TypeId::of::<T>(),
 | 
			
		||||
            fields: fields.to_vec().into_boxed_slice(),
 | 
			
		||||
            #[cfg(feature = "documentation")]
 | 
			
		||||
@ -103,20 +101,21 @@ impl TupleStructInfo {
 | 
			
		||||
        self.fields.len()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The name of the struct.
 | 
			
		||||
    /// A representation of the type path of the struct.
 | 
			
		||||
    ///
 | 
			
		||||
    /// This does _not_ include any generics or lifetimes.
 | 
			
		||||
    ///
 | 
			
		||||
    /// For example, `foo::bar::Baz<'a, T>` would simply be `Baz`.
 | 
			
		||||
    pub fn name(&self) -> &'static str {
 | 
			
		||||
        self.name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the tuple struct.
 | 
			
		||||
    /// The [stable, full type path] of the struct.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn type_name(&self) -> &'static str {
 | 
			
		||||
        self.type_name
 | 
			
		||||
    /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// [stable, full type path]: TypePath
 | 
			
		||||
    /// [`type_path_table`]: Self::type_path_table
 | 
			
		||||
    pub fn type_path(&self) -> &'static str {
 | 
			
		||||
        self.type_path_table().path()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the tuple struct.
 | 
			
		||||
@ -295,13 +294,6 @@ impl TupleStruct for DynamicTupleStruct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Reflect for DynamicTupleStruct {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn type_name(&self) -> &str {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
            .map(|info| info.type_name())
 | 
			
		||||
            .unwrap_or_else(|| std::any::type_name::<Self>())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
			
		||||
        self.represented_type
 | 
			
		||||
@ -452,7 +444,7 @@ pub fn tuple_struct_debug(
 | 
			
		||||
    dyn_tuple_struct: &dyn TupleStruct,
 | 
			
		||||
    f: &mut std::fmt::Formatter<'_>,
 | 
			
		||||
) -> std::fmt::Result {
 | 
			
		||||
    let mut debug = f.debug_tuple(dyn_tuple_struct.type_name());
 | 
			
		||||
    let mut debug = f.debug_tuple(dyn_tuple_struct.reflect_type_path());
 | 
			
		||||
    for field in dyn_tuple_struct.iter_fields() {
 | 
			
		||||
        debug.field(&field as &dyn Debug);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
use crate::{
 | 
			
		||||
    ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo,
 | 
			
		||||
    TypePath, TypePathTable,
 | 
			
		||||
};
 | 
			
		||||
use std::any::{Any, TypeId};
 | 
			
		||||
use std::fmt::Debug;
 | 
			
		||||
@ -41,15 +42,17 @@ use std::fmt::Debug;
 | 
			
		||||
///         NamedField::new::<usize >("foo"),
 | 
			
		||||
///         NamedField::new::<(f32, f32) >("bar"),
 | 
			
		||||
///       ];
 | 
			
		||||
///       let info = StructInfo::new::<Self>("MyStruct", &fields);
 | 
			
		||||
///       let info = StructInfo::new::<Self>(&fields);
 | 
			
		||||
///       TypeInfo::Struct(info)
 | 
			
		||||
///     })
 | 
			
		||||
///   }
 | 
			
		||||
/// }
 | 
			
		||||
///
 | 
			
		||||
/// #
 | 
			
		||||
/// # impl TypePath for MyStruct {
 | 
			
		||||
/// #     fn type_path() -> &'static str { todo!() }
 | 
			
		||||
/// #     fn short_type_path() -> &'static str { todo!() }
 | 
			
		||||
/// # }
 | 
			
		||||
/// # impl Reflect for MyStruct {
 | 
			
		||||
/// #   fn type_name(&self) -> &str { todo!() }
 | 
			
		||||
/// #   fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
 | 
			
		||||
/// #   fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
 | 
			
		||||
/// #   fn as_any(&self) -> &dyn Any { todo!() }
 | 
			
		||||
@ -64,15 +67,10 @@ use std::fmt::Debug;
 | 
			
		||||
/// #   fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
 | 
			
		||||
/// #   fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
 | 
			
		||||
/// # }
 | 
			
		||||
/// #
 | 
			
		||||
/// # impl TypePath for MyStruct {
 | 
			
		||||
/// #   fn type_path() -> &'static str { todo!() }
 | 
			
		||||
/// #   fn short_type_path() -> &'static str { todo!() }
 | 
			
		||||
/// # }
 | 
			
		||||
/// ```
 | 
			
		||||
///
 | 
			
		||||
/// [utility]: crate::utility
 | 
			
		||||
pub trait Typed: Reflect {
 | 
			
		||||
pub trait Typed: Reflect + TypePath {
 | 
			
		||||
    /// Returns the compile-time [info] for the underlying type.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [info]: TypeInfo
 | 
			
		||||
@ -90,7 +88,7 @@ pub trait Typed: Reflect {
 | 
			
		||||
/// Each return a static reference to [`TypeInfo`], but they all have their own use cases.
 | 
			
		||||
/// For example, if you know the type at compile time, [`Typed::type_info`] is probably
 | 
			
		||||
/// the simplest. If all you have is a `dyn Reflect`, you'll probably want [`Reflect::get_represented_type_info`].
 | 
			
		||||
/// Lastly, if all you have is a [`TypeId`] or [type name], you will need to go through
 | 
			
		||||
/// Lastly, if all you have is a [`TypeId`] or [type path], you will need to go through
 | 
			
		||||
/// [`TypeRegistry::get_type_info`].
 | 
			
		||||
///
 | 
			
		||||
/// You may also opt to use [`TypeRegistry::get_type_info`] in place of the other methods simply because
 | 
			
		||||
@ -100,7 +98,7 @@ pub trait Typed: Reflect {
 | 
			
		||||
/// [`Reflect::get_represented_type_info`]: crate::Reflect::get_represented_type_info
 | 
			
		||||
/// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info
 | 
			
		||||
/// [`TypeId`]: std::any::TypeId
 | 
			
		||||
/// [type name]: std::any::type_name
 | 
			
		||||
/// [type path]: TypePath::type_path
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub enum TypeInfo {
 | 
			
		||||
    Struct(StructInfo),
 | 
			
		||||
@ -128,22 +126,32 @@ impl TypeInfo {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [name] of the underlying type.
 | 
			
		||||
    /// A representation of the type path of the underlying type.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [name]: std::any::type_name
 | 
			
		||||
    pub fn type_name(&self) -> &'static str {
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        match self {
 | 
			
		||||
            Self::Struct(info) => info.type_name(),
 | 
			
		||||
            Self::TupleStruct(info) => info.type_name(),
 | 
			
		||||
            Self::Tuple(info) => info.type_name(),
 | 
			
		||||
            Self::List(info) => info.type_name(),
 | 
			
		||||
            Self::Array(info) => info.type_name(),
 | 
			
		||||
            Self::Map(info) => info.type_name(),
 | 
			
		||||
            Self::Enum(info) => info.type_name(),
 | 
			
		||||
            Self::Value(info) => info.type_name(),
 | 
			
		||||
            Self::Struct(info) => info.type_path_table(),
 | 
			
		||||
            Self::TupleStruct(info) => info.type_path_table(),
 | 
			
		||||
            Self::Tuple(info) => info.type_path_table(),
 | 
			
		||||
            Self::List(info) => info.type_path_table(),
 | 
			
		||||
            Self::Array(info) => info.type_path_table(),
 | 
			
		||||
            Self::Map(info) => info.type_path_table(),
 | 
			
		||||
            Self::Enum(info) => info.type_path_table(),
 | 
			
		||||
            Self::Value(info) => info.type_path_table(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [stable, full type path] of the underlying type.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// [stable, full type path]: TypePath
 | 
			
		||||
    /// [`type_path_table`]: Self::type_path_table
 | 
			
		||||
    pub fn type_path(&self) -> &'static str {
 | 
			
		||||
        self.type_path_table().path()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Check if the given type matches the underlying type.
 | 
			
		||||
    pub fn is<T: Any>(&self) -> bool {
 | 
			
		||||
        TypeId::of::<T>() == self.type_id()
 | 
			
		||||
@ -175,16 +183,16 @@ impl TypeInfo {
 | 
			
		||||
/// it _as_ a struct. It therefore makes more sense to represent it as a [`ValueInfo`].
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub struct ValueInfo {
 | 
			
		||||
    type_name: &'static str,
 | 
			
		||||
    type_path: TypePathTable,
 | 
			
		||||
    type_id: TypeId,
 | 
			
		||||
    #[cfg(feature = "documentation")]
 | 
			
		||||
    docs: Option<&'static str>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ValueInfo {
 | 
			
		||||
    pub fn new<T: Reflect + ?Sized>() -> Self {
 | 
			
		||||
    pub fn new<T: Reflect + TypePath + ?Sized>() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            type_name: std::any::type_name::<T>(),
 | 
			
		||||
            type_path: TypePathTable::of::<T>(),
 | 
			
		||||
            type_id: TypeId::of::<T>(),
 | 
			
		||||
            #[cfg(feature = "documentation")]
 | 
			
		||||
            docs: None,
 | 
			
		||||
@ -197,11 +205,21 @@ impl ValueInfo {
 | 
			
		||||
        Self { docs: doc, ..self }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [type name] of the value.
 | 
			
		||||
    /// A representation of the type path of the value.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type name]: std::any::type_name
 | 
			
		||||
    pub fn type_name(&self) -> &'static str {
 | 
			
		||||
        self.type_name
 | 
			
		||||
    /// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
    pub fn type_path_table(&self) -> &TypePathTable {
 | 
			
		||||
        &self.type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [stable, full type path] of the value.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// [stable, full type path]: TypePath
 | 
			
		||||
    /// [`type_path_table`]: Self::type_path_table
 | 
			
		||||
    pub fn type_path(&self) -> &'static str {
 | 
			
		||||
        self.type_path_table().path()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The [`TypeId`] of the value.
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
use std::fmt;
 | 
			
		||||
 | 
			
		||||
/// A static accessor to type paths and names.
 | 
			
		||||
///
 | 
			
		||||
/// The engine uses this trait over [`std::any::type_name`] for stability and flexibility.
 | 
			
		||||
@ -82,21 +84,21 @@ pub trait TypePath: 'static {
 | 
			
		||||
    ///
 | 
			
		||||
    /// Generic parameter types are also fully expanded.
 | 
			
		||||
    ///
 | 
			
		||||
    /// For `Option<PhantomData>`, this is `"core::option::Option<core::marker::PhantomData>"`.
 | 
			
		||||
    /// For `Option<Vec<usize>>`, this is `"core::option::Option<alloc::vec::Vec<usize>>"`.
 | 
			
		||||
    fn type_path() -> &'static str;
 | 
			
		||||
 | 
			
		||||
    /// Returns a short, pretty-print enabled path to the type.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Generic parameter types are also shortened.
 | 
			
		||||
    ///
 | 
			
		||||
    /// For `Option<PhantomData>`, this is `"Option<PhantomData>"`.
 | 
			
		||||
    /// For `Option<Vec<usize>>`, this is `"Option<Vec<usize>>"`.
 | 
			
		||||
    fn short_type_path() -> &'static str;
 | 
			
		||||
 | 
			
		||||
    /// Returns the name of the type, or [`None`] if it is [anonymous].
 | 
			
		||||
    ///
 | 
			
		||||
    /// Primitive types will return [`Some`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// For `Option<PhantomData>`, this is `"Option"`.
 | 
			
		||||
    /// For `Option<Vec<usize>>`, this is `"Option"`.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [anonymous]: TypePath#anonymity
 | 
			
		||||
    fn type_ident() -> Option<&'static str> {
 | 
			
		||||
@ -105,7 +107,7 @@ pub trait TypePath: 'static {
 | 
			
		||||
 | 
			
		||||
    /// Returns the name of the crate the type is in, or [`None`] if it is [anonymous].
 | 
			
		||||
    ///
 | 
			
		||||
    /// For `Option<PhantomData>`, this is `"core"`.
 | 
			
		||||
    /// For `Option<Vec<usize>>`, this is `"core"`.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [anonymous]: TypePath#anonymity
 | 
			
		||||
    fn crate_name() -> Option<&'static str> {
 | 
			
		||||
@ -114,7 +116,7 @@ pub trait TypePath: 'static {
 | 
			
		||||
 | 
			
		||||
    /// Returns the path to the module the type is in, or [`None`] if it is [anonymous].
 | 
			
		||||
    ///
 | 
			
		||||
    /// For `Option<PhantomData>`, this is `"core::option"`.
 | 
			
		||||
    /// For `Option<Vec<usize>>`, this is `"core::option"`.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [anonymous]: TypePath#anonymity
 | 
			
		||||
    fn module_path() -> Option<&'static str> {
 | 
			
		||||
@ -123,6 +125,10 @@ pub trait TypePath: 'static {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Dynamic dispatch for [`TypePath`].
 | 
			
		||||
///
 | 
			
		||||
/// Since this is a supertrait of [`Reflect`] its methods can be called on a `dyn Reflect`.
 | 
			
		||||
///
 | 
			
		||||
/// [`Reflect`]: crate::Reflect
 | 
			
		||||
pub trait DynamicTypePath {
 | 
			
		||||
    /// See [`TypePath::type_path`].
 | 
			
		||||
    fn reflect_type_path(&self) -> &str;
 | 
			
		||||
@ -161,3 +167,60 @@ impl<T: TypePath> DynamicTypePath for T {
 | 
			
		||||
        Self::module_path()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Provides dynamic access to all methods on [`TypePath`].
 | 
			
		||||
#[derive(Clone, Copy)]
 | 
			
		||||
pub struct TypePathTable {
 | 
			
		||||
    // Cache the type path as it is likely the only one that will be used.
 | 
			
		||||
    type_path: &'static str,
 | 
			
		||||
    short_type_path: fn() -> &'static str,
 | 
			
		||||
    type_ident: fn() -> Option<&'static str>,
 | 
			
		||||
    crate_name: fn() -> Option<&'static str>,
 | 
			
		||||
    module_path: fn() -> Option<&'static str>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Debug for TypePathTable {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
			
		||||
        f.debug_struct("TypePathVtable")
 | 
			
		||||
            .field("type_path", &self.type_path)
 | 
			
		||||
            .finish()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TypePathTable {
 | 
			
		||||
    /// Creates a new table from a type.
 | 
			
		||||
    pub fn of<T: TypePath + ?Sized>() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            type_path: T::type_path(),
 | 
			
		||||
            short_type_path: T::short_type_path,
 | 
			
		||||
            type_ident: T::type_ident,
 | 
			
		||||
            crate_name: T::crate_name,
 | 
			
		||||
            module_path: T::module_path,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// See [`TypePath::type_path`].
 | 
			
		||||
    pub fn path(&self) -> &'static str {
 | 
			
		||||
        self.type_path
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// See [`TypePath::short_type_path`].
 | 
			
		||||
    pub fn short_path(&self) -> &'static str {
 | 
			
		||||
        (self.short_type_path)()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// See [`TypePath::type_ident`].
 | 
			
		||||
    pub fn ident(&self) -> Option<&'static str> {
 | 
			
		||||
        (self.type_ident)()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// See [`TypePath::crate_name`].
 | 
			
		||||
    pub fn crate_name(&self) -> Option<&'static str> {
 | 
			
		||||
        (self.crate_name)()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// See [`TypePath::module_path`].
 | 
			
		||||
    pub fn module_path(&self) -> Option<&'static str> {
 | 
			
		||||
        (self.module_path)()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
use crate::{serde::Serializable, Reflect, TypeInfo, Typed};
 | 
			
		||||
use crate::{serde::Serializable, Reflect, TypeInfo, TypePath, Typed};
 | 
			
		||||
use bevy_ptr::{Ptr, PtrMut};
 | 
			
		||||
use bevy_utils::{HashMap, HashSet};
 | 
			
		||||
use downcast_rs::{impl_downcast, Downcast};
 | 
			
		||||
@ -23,9 +23,9 @@ use std::{
 | 
			
		||||
/// [crate-level documentation]: crate
 | 
			
		||||
pub struct TypeRegistry {
 | 
			
		||||
    registrations: HashMap<TypeId, TypeRegistration>,
 | 
			
		||||
    short_name_to_id: HashMap<String, TypeId>,
 | 
			
		||||
    full_name_to_id: HashMap<String, TypeId>,
 | 
			
		||||
    ambiguous_names: HashSet<String>,
 | 
			
		||||
    short_path_to_id: HashMap<&'static str, TypeId>,
 | 
			
		||||
    type_path_to_id: HashMap<&'static str, TypeId>,
 | 
			
		||||
    ambiguous_names: HashSet<&'static str>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO:  remove this wrapper once we migrate to Atelier Assets and the Scene AssetLoader doesn't
 | 
			
		||||
@ -41,7 +41,7 @@ impl Debug for TypeRegistryArc {
 | 
			
		||||
        self.internal
 | 
			
		||||
            .read()
 | 
			
		||||
            .unwrap_or_else(PoisonError::into_inner)
 | 
			
		||||
            .full_name_to_id
 | 
			
		||||
            .type_path_to_id
 | 
			
		||||
            .keys()
 | 
			
		||||
            .fmt(f)
 | 
			
		||||
    }
 | 
			
		||||
@ -71,8 +71,8 @@ impl TypeRegistry {
 | 
			
		||||
    pub fn empty() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            registrations: Default::default(),
 | 
			
		||||
            short_name_to_id: Default::default(),
 | 
			
		||||
            full_name_to_id: Default::default(),
 | 
			
		||||
            short_path_to_id: Default::default(),
 | 
			
		||||
            type_path_to_id: Default::default(),
 | 
			
		||||
            ambiguous_names: Default::default(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -118,19 +118,19 @@ impl TypeRegistry {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let short_name = registration.short_name.to_string();
 | 
			
		||||
        if self.short_name_to_id.contains_key(&short_name)
 | 
			
		||||
            || self.ambiguous_names.contains(&short_name)
 | 
			
		||||
        let short_name = registration.type_info().type_path_table().short_path();
 | 
			
		||||
        if self.short_path_to_id.contains_key(short_name)
 | 
			
		||||
            || self.ambiguous_names.contains(short_name)
 | 
			
		||||
        {
 | 
			
		||||
            // name is ambiguous. fall back to long names for all ambiguous types
 | 
			
		||||
            self.short_name_to_id.remove(&short_name);
 | 
			
		||||
            self.short_path_to_id.remove(short_name);
 | 
			
		||||
            self.ambiguous_names.insert(short_name);
 | 
			
		||||
        } else {
 | 
			
		||||
            self.short_name_to_id
 | 
			
		||||
            self.short_path_to_id
 | 
			
		||||
                .insert(short_name, registration.type_id());
 | 
			
		||||
        }
 | 
			
		||||
        self.full_name_to_id
 | 
			
		||||
            .insert(registration.type_name().to_string(), registration.type_id());
 | 
			
		||||
        self.type_path_to_id
 | 
			
		||||
            .insert(registration.type_info().type_path(), registration.type_id());
 | 
			
		||||
        self.registrations
 | 
			
		||||
            .insert(registration.type_id(), registration);
 | 
			
		||||
    }
 | 
			
		||||
@ -151,11 +151,11 @@ impl TypeRegistry {
 | 
			
		||||
    /// type_registry.register_type_data::<Option<String>, ReflectSerialize>();
 | 
			
		||||
    /// type_registry.register_type_data::<Option<String>, ReflectDeserialize>();
 | 
			
		||||
    /// ```
 | 
			
		||||
    pub fn register_type_data<T: Reflect + 'static, D: TypeData + FromType<T>>(&mut self) {
 | 
			
		||||
    pub fn register_type_data<T: Reflect + TypePath, D: TypeData + FromType<T>>(&mut self) {
 | 
			
		||||
        let data = self.get_mut(TypeId::of::<T>()).unwrap_or_else(|| {
 | 
			
		||||
            panic!(
 | 
			
		||||
                "attempted to call `TypeRegistry::register_type_data` for type `{T}` with data `{D}` without registering `{T}` first",
 | 
			
		||||
                T = std::any::type_name::<T>(),
 | 
			
		||||
                T = T::type_path(),
 | 
			
		||||
                D = std::any::type_name::<D>(),
 | 
			
		||||
            )
 | 
			
		||||
        });
 | 
			
		||||
@ -183,48 +183,56 @@ impl TypeRegistry {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns a reference to the [`TypeRegistration`] of the type with the
 | 
			
		||||
    /// given name.
 | 
			
		||||
    /// given [type path].
 | 
			
		||||
    ///
 | 
			
		||||
    /// If no type with the given name has been registered, returns `None`.
 | 
			
		||||
    pub fn get_with_name(&self, type_name: &str) -> Option<&TypeRegistration> {
 | 
			
		||||
        self.full_name_to_id
 | 
			
		||||
            .get(type_name)
 | 
			
		||||
    /// If no type with the given path has been registered, returns `None`.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type path]: TypePath::type_path
 | 
			
		||||
    pub fn get_with_type_path(&self, type_path: &str) -> Option<&TypeRegistration> {
 | 
			
		||||
        self.type_path_to_id
 | 
			
		||||
            .get(type_path)
 | 
			
		||||
            .and_then(|id| self.get(*id))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns a mutable reference to the [`TypeRegistration`] of the type with
 | 
			
		||||
    /// the given name.
 | 
			
		||||
    /// the given [type path].
 | 
			
		||||
    ///
 | 
			
		||||
    /// If no type with the given name has been registered, returns `None`.
 | 
			
		||||
    pub fn get_with_name_mut(&mut self, type_name: &str) -> Option<&mut TypeRegistration> {
 | 
			
		||||
        self.full_name_to_id
 | 
			
		||||
            .get(type_name)
 | 
			
		||||
    /// If no type with the given type path has been registered, returns `None`.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type path]: TypePath::type_path
 | 
			
		||||
    pub fn get_with_type_path_mut(&mut self, type_path: &str) -> Option<&mut TypeRegistration> {
 | 
			
		||||
        self.type_path_to_id
 | 
			
		||||
            .get(type_path)
 | 
			
		||||
            .cloned()
 | 
			
		||||
            .and_then(move |id| self.get_mut(id))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns a reference to the [`TypeRegistration`] of the type with
 | 
			
		||||
    /// the given short name.
 | 
			
		||||
    /// the given [short type path].
 | 
			
		||||
    ///
 | 
			
		||||
    /// If the short name is ambiguous, or if no type with the given short name
 | 
			
		||||
    /// If the short type path is ambiguous, or if no type with the given path
 | 
			
		||||
    /// has been registered, returns `None`.
 | 
			
		||||
    pub fn get_with_short_name(&self, short_type_name: &str) -> Option<&TypeRegistration> {
 | 
			
		||||
        self.short_name_to_id
 | 
			
		||||
            .get(short_type_name)
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type path]: TypePath::short_type_path
 | 
			
		||||
    pub fn get_with_short_type_path(&self, short_type_path: &str) -> Option<&TypeRegistration> {
 | 
			
		||||
        self.short_path_to_id
 | 
			
		||||
            .get(short_type_path)
 | 
			
		||||
            .and_then(|id| self.registrations.get(id))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns a mutable reference to the [`TypeRegistration`] of the type with
 | 
			
		||||
    /// the given short name.
 | 
			
		||||
    /// the given [short type path].
 | 
			
		||||
    ///
 | 
			
		||||
    /// If the short name is ambiguous, or if no type with the given short name
 | 
			
		||||
    /// If the short type path is ambiguous, or if no type with the given path
 | 
			
		||||
    /// has been registered, returns `None`.
 | 
			
		||||
    pub fn get_with_short_name_mut(
 | 
			
		||||
    ///
 | 
			
		||||
    /// [type path]: TypePath::short_type_path
 | 
			
		||||
    pub fn get_with_short_type_path_mut(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        short_type_name: &str,
 | 
			
		||||
        short_type_path: &str,
 | 
			
		||||
    ) -> Option<&mut TypeRegistration> {
 | 
			
		||||
        self.short_name_to_id
 | 
			
		||||
            .get(short_type_name)
 | 
			
		||||
        self.short_path_to_id
 | 
			
		||||
            .get(short_type_path)
 | 
			
		||||
            .and_then(|id| self.registrations.get_mut(id))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -292,7 +300,7 @@ impl TypeRegistryArc {
 | 
			
		||||
/// but is more often automatically generated using [`#[derive(Reflect)]`](derive@crate::Reflect) which itself generates
 | 
			
		||||
/// an implementation of the [`GetTypeRegistration`] trait.
 | 
			
		||||
///
 | 
			
		||||
/// Along with the type's [`TypeInfo`] and [short name],
 | 
			
		||||
/// Along with the type's [`TypeInfo`],
 | 
			
		||||
/// this struct also contains a type's registered [`TypeData`].
 | 
			
		||||
///
 | 
			
		||||
/// See the [crate-level documentation] for more information on type registration.
 | 
			
		||||
@ -303,17 +311,15 @@ impl TypeRegistryArc {
 | 
			
		||||
/// # use bevy_reflect::{TypeRegistration, std_traits::ReflectDefault, FromType};
 | 
			
		||||
/// let mut registration = TypeRegistration::of::<Option<String>>();
 | 
			
		||||
///
 | 
			
		||||
/// assert_eq!("core::option::Option<alloc::string::String>", registration.type_name());
 | 
			
		||||
/// assert_eq!("Option<String>", registration.short_name());
 | 
			
		||||
/// assert_eq!("core::option::Option<alloc::string::String>", registration.type_info().type_path());
 | 
			
		||||
/// assert_eq!("Option<String>", registration.type_info().type_path_table().short_path());
 | 
			
		||||
///
 | 
			
		||||
/// registration.insert::<ReflectDefault>(FromType::<Option<String>>::from_type());
 | 
			
		||||
/// assert!(registration.data::<ReflectDefault>().is_some())
 | 
			
		||||
/// ```
 | 
			
		||||
///
 | 
			
		||||
/// [short name]: bevy_utils::get_short_name
 | 
			
		||||
/// [crate-level documentation]: crate
 | 
			
		||||
pub struct TypeRegistration {
 | 
			
		||||
    short_name: String,
 | 
			
		||||
    data: HashMap<TypeId, Box<dyn TypeData>>,
 | 
			
		||||
    type_info: &'static TypeInfo,
 | 
			
		||||
}
 | 
			
		||||
@ -321,7 +327,6 @@ pub struct TypeRegistration {
 | 
			
		||||
impl Debug for TypeRegistration {
 | 
			
		||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
        f.debug_struct("TypeRegistration")
 | 
			
		||||
            .field("short_name", &self.short_name)
 | 
			
		||||
            .field("type_info", &self.type_info)
 | 
			
		||||
            .finish()
 | 
			
		||||
    }
 | 
			
		||||
@ -369,28 +374,12 @@ impl TypeRegistration {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Creates type registration information for `T`.
 | 
			
		||||
    pub fn of<T: Reflect + Typed>() -> Self {
 | 
			
		||||
        let type_name = std::any::type_name::<T>();
 | 
			
		||||
    pub fn of<T: Reflect + Typed + TypePath>() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            data: HashMap::default(),
 | 
			
		||||
            short_name: bevy_utils::get_short_name(type_name),
 | 
			
		||||
            type_info: T::type_info(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns the [short name] of the type.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [short name]: bevy_utils::get_short_name
 | 
			
		||||
    pub fn short_name(&self) -> &str {
 | 
			
		||||
        &self.short_name
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns the [name] of the type.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [name]: std::any::type_name
 | 
			
		||||
    pub fn type_name(&self) -> &'static str {
 | 
			
		||||
        self.type_info.type_name()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Clone for TypeRegistration {
 | 
			
		||||
@ -402,7 +391,6 @@ impl Clone for TypeRegistration {
 | 
			
		||||
 | 
			
		||||
        TypeRegistration {
 | 
			
		||||
            data,
 | 
			
		||||
            short_name: self.short_name.clone(),
 | 
			
		||||
            type_info: self.type_info,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -455,7 +443,7 @@ impl<T: Reflect + erased_serde::Serialize> FromType<T> for ReflectSerialize {
 | 
			
		||||
        ReflectSerialize {
 | 
			
		||||
            get_serializable: |value| {
 | 
			
		||||
                let value = value.downcast_ref::<T>().unwrap_or_else(|| {
 | 
			
		||||
                    panic!("ReflectSerialize::get_serialize called with type `{}`, even though it was created for `{}`", value.type_name(), std::any::type_name::<T>())
 | 
			
		||||
                    panic!("ReflectSerialize::get_serialize called with type `{}`, even though it was created for `{}`", value.reflect_type_path(), std::any::type_name::<T>())
 | 
			
		||||
                });
 | 
			
		||||
                Serializable::Borrowed(value)
 | 
			
		||||
            },
 | 
			
		||||
@ -611,9 +599,8 @@ impl<T: Reflect> FromType<T> for ReflectFromPtr {
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod test {
 | 
			
		||||
    use crate::{GetTypeRegistration, ReflectFromPtr, TypeRegistration};
 | 
			
		||||
    use crate::{GetTypeRegistration, ReflectFromPtr};
 | 
			
		||||
    use bevy_ptr::{Ptr, PtrMut};
 | 
			
		||||
    use bevy_utils::HashMap;
 | 
			
		||||
 | 
			
		||||
    use crate as bevy_reflect;
 | 
			
		||||
    use crate::Reflect;
 | 
			
		||||
@ -658,37 +645,4 @@ mod test {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_property_type_registration() {
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            TypeRegistration::of::<Option<f64>>().short_name,
 | 
			
		||||
            "Option<f64>"
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            TypeRegistration::of::<HashMap<u32, String>>().short_name,
 | 
			
		||||
            "HashMap<u32, String>"
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            TypeRegistration::of::<Option<HashMap<u32, String>>>().short_name,
 | 
			
		||||
            "Option<HashMap<u32, String>>"
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            TypeRegistration::of::<Option<HashMap<u32, Option<String>>>>().short_name,
 | 
			
		||||
            "Option<HashMap<u32, Option<String>>>"
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            TypeRegistration::of::<Option<HashMap<String, Option<String>>>>().short_name,
 | 
			
		||||
            "Option<HashMap<String, Option<String>>>"
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            TypeRegistration::of::<Option<HashMap<Option<String>, Option<String>>>>().short_name,
 | 
			
		||||
            "Option<HashMap<Option<String>, Option<String>>>"
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            TypeRegistration::of::<Option<HashMap<Option<String>, (String, Option<String>)>>>()
 | 
			
		||||
                .short_name,
 | 
			
		||||
            "Option<HashMap<Option<String>, (String, Option<String>)>>"
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -62,14 +62,16 @@ mod sealed {
 | 
			
		||||
///         static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
 | 
			
		||||
///         CELL.get_or_set(|| {
 | 
			
		||||
///             let fields = [NamedField::new::<i32>("bar")];
 | 
			
		||||
///             let info = StructInfo::new::<Self>("Foo", &fields);
 | 
			
		||||
///             let info = StructInfo::new::<Self>(&fields);
 | 
			
		||||
///             TypeInfo::Struct(info)
 | 
			
		||||
///         })
 | 
			
		||||
///     }
 | 
			
		||||
/// }
 | 
			
		||||
/// #
 | 
			
		||||
/// # impl TypePath for Foo {
 | 
			
		||||
/// #     fn type_path() -> &'static str { todo!() }
 | 
			
		||||
/// #     fn short_type_path() -> &'static str { todo!() }
 | 
			
		||||
/// # }
 | 
			
		||||
/// # impl Reflect for Foo {
 | 
			
		||||
/// #     fn type_name(&self) -> &str { todo!() }
 | 
			
		||||
/// #     fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
 | 
			
		||||
/// #     fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
 | 
			
		||||
/// #     fn as_any(&self) -> &dyn Any { todo!() }
 | 
			
		||||
@ -84,11 +86,6 @@ mod sealed {
 | 
			
		||||
/// #     fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
 | 
			
		||||
/// #     fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
 | 
			
		||||
/// # }
 | 
			
		||||
 | 
			
		||||
/// # impl TypePath for Foo {
 | 
			
		||||
/// #   fn type_path() -> &'static str { todo!() }
 | 
			
		||||
/// #   fn short_type_path() -> &'static str { todo!() }
 | 
			
		||||
/// # }
 | 
			
		||||
/// ```
 | 
			
		||||
///
 | 
			
		||||
/// [`TypePath`]: crate::TypePath
 | 
			
		||||
@ -133,19 +130,21 @@ impl<T: TypedProperty> NonGenericTypeCell<T> {
 | 
			
		||||
///
 | 
			
		||||
/// struct Foo<T>(T);
 | 
			
		||||
///
 | 
			
		||||
/// impl<T: Reflect> Typed for Foo<T> {
 | 
			
		||||
/// impl<T: Reflect + TypePath> Typed for Foo<T> {
 | 
			
		||||
///     fn type_info() -> &'static TypeInfo {
 | 
			
		||||
///         static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
 | 
			
		||||
///         CELL.get_or_insert::<Self, _>(|| {
 | 
			
		||||
///             let fields = [UnnamedField::new::<T>(0)];
 | 
			
		||||
///             let info = TupleStructInfo::new::<Self>("Foo", &fields);
 | 
			
		||||
///             let info = TupleStructInfo::new::<Self>(&fields);
 | 
			
		||||
///             TypeInfo::TupleStruct(info)
 | 
			
		||||
///         })
 | 
			
		||||
///     }
 | 
			
		||||
/// }
 | 
			
		||||
/// #
 | 
			
		||||
/// # impl<T: Reflect> Reflect for Foo<T> {
 | 
			
		||||
/// #     fn type_name(&self) -> &str { todo!() }
 | 
			
		||||
/// # impl<T: TypePath> TypePath for Foo<T> {
 | 
			
		||||
/// #     fn type_path() -> &'static str { todo!() }
 | 
			
		||||
/// #     fn short_type_path() -> &'static str { todo!() }
 | 
			
		||||
/// # }
 | 
			
		||||
/// # impl<T: Reflect + TypePath> Reflect for Foo<T> {
 | 
			
		||||
/// #     fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
 | 
			
		||||
/// #     fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
 | 
			
		||||
/// #     fn as_any(&self) -> &dyn Any { todo!() }
 | 
			
		||||
@ -160,22 +159,18 @@ impl<T: TypedProperty> NonGenericTypeCell<T> {
 | 
			
		||||
/// #     fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
 | 
			
		||||
/// #     fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
 | 
			
		||||
/// # }
 | 
			
		||||
/// # impl<T: Reflect> TypePath for Foo<T> {
 | 
			
		||||
/// #   fn type_path() -> &'static str { todo!() }
 | 
			
		||||
/// #   fn short_type_path() -> &'static str { todo!() }
 | 
			
		||||
/// # }
 | 
			
		||||
/// ```
 | 
			
		||||
///
 | 
			
		||||
///  Implementing [`TypePath`] with generics.
 | 
			
		||||
///
 | 
			
		||||
/// ```
 | 
			
		||||
/// # use std::any::Any;
 | 
			
		||||
/// # use bevy_reflect::{DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath};
 | 
			
		||||
/// # use bevy_reflect::TypePath;
 | 
			
		||||
/// use bevy_reflect::utility::GenericTypePathCell;
 | 
			
		||||
///
 | 
			
		||||
/// struct Foo<T>(T);
 | 
			
		||||
///
 | 
			
		||||
/// impl<T: Reflect + TypePath> TypePath for Foo<T> {
 | 
			
		||||
/// impl<T: TypePath> TypePath for Foo<T> {
 | 
			
		||||
///     fn type_path() -> &'static str {
 | 
			
		||||
///         static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
///         CELL.get_or_insert::<Self, _>(|| format!("my_crate::foo::Foo<{}>", T::type_path()))
 | 
			
		||||
@ -185,24 +180,19 @@ impl<T: TypedProperty> NonGenericTypeCell<T> {
 | 
			
		||||
///         static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
			
		||||
///         CELL.get_or_insert::<Self, _>(|| format!("Foo<{}>", T::short_type_path()))
 | 
			
		||||
///     }
 | 
			
		||||
///
 | 
			
		||||
///     fn type_ident() -> Option<&'static str> {
 | 
			
		||||
///         Some("Foo")
 | 
			
		||||
///     }
 | 
			
		||||
///
 | 
			
		||||
///     fn module_path() -> Option<&'static str> {
 | 
			
		||||
///         Some("my_crate::foo")
 | 
			
		||||
///     }
 | 
			
		||||
///
 | 
			
		||||
///     fn crate_name() -> Option<&'static str> {
 | 
			
		||||
///         Some("my_crate")
 | 
			
		||||
///     }
 | 
			
		||||
/// }
 | 
			
		||||
/// #
 | 
			
		||||
/// # impl<T: Reflect + TypePath> Reflect for Foo<T> {
 | 
			
		||||
/// #     fn type_name(&self) -> &str { todo!() }
 | 
			
		||||
/// #     fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
 | 
			
		||||
/// #     fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
 | 
			
		||||
/// #     fn as_any(&self) -> &dyn Any { todo!() }
 | 
			
		||||
/// #     fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }
 | 
			
		||||
/// #     fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> { todo!() }
 | 
			
		||||
/// #     fn as_reflect(&self) -> &dyn Reflect { todo!() }
 | 
			
		||||
/// #     fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() }
 | 
			
		||||
/// #     fn apply(&mut self, value: &dyn Reflect) { todo!() }
 | 
			
		||||
/// #     fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() }
 | 
			
		||||
/// #     fn reflect_ref(&self) -> ReflectRef { todo!() }
 | 
			
		||||
/// #     fn reflect_mut(&mut self) -> ReflectMut { todo!() }
 | 
			
		||||
/// #     fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
 | 
			
		||||
/// #     fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
 | 
			
		||||
/// # }
 | 
			
		||||
/// ```
 | 
			
		||||
/// [`impl_type_path`]: crate::impl_type_path
 | 
			
		||||
/// [`TypePath`]: crate::TypePath
 | 
			
		||||
 | 
			
		||||
@ -73,14 +73,19 @@ impl DynamicScene {
 | 
			
		||||
        let type_registry = type_registry.read();
 | 
			
		||||
 | 
			
		||||
        for resource in &self.resources {
 | 
			
		||||
            let registration = type_registry
 | 
			
		||||
                .get_with_name(resource.type_name())
 | 
			
		||||
                .ok_or_else(|| SceneSpawnError::UnregisteredType {
 | 
			
		||||
                    type_name: resource.type_name().to_string(),
 | 
			
		||||
            let type_info = resource.get_represented_type_info().ok_or_else(|| {
 | 
			
		||||
                SceneSpawnError::NoRepresentedType {
 | 
			
		||||
                    type_path: resource.reflect_type_path().to_string(),
 | 
			
		||||
                }
 | 
			
		||||
            })?;
 | 
			
		||||
            let registration = type_registry.get(type_info.type_id()).ok_or_else(|| {
 | 
			
		||||
                SceneSpawnError::UnregisteredButReflectedType {
 | 
			
		||||
                    type_path: type_info.type_path().to_string(),
 | 
			
		||||
                }
 | 
			
		||||
            })?;
 | 
			
		||||
            let reflect_resource = registration.data::<ReflectResource>().ok_or_else(|| {
 | 
			
		||||
                SceneSpawnError::UnregisteredResource {
 | 
			
		||||
                    type_name: resource.type_name().to_string(),
 | 
			
		||||
                    type_path: type_info.type_path().to_string(),
 | 
			
		||||
                }
 | 
			
		||||
            })?;
 | 
			
		||||
 | 
			
		||||
@ -106,15 +111,20 @@ impl DynamicScene {
 | 
			
		||||
 | 
			
		||||
            // Apply/ add each component to the given entity.
 | 
			
		||||
            for component in &scene_entity.components {
 | 
			
		||||
                let registration = type_registry
 | 
			
		||||
                    .get_with_name(component.type_name())
 | 
			
		||||
                    .ok_or_else(|| SceneSpawnError::UnregisteredType {
 | 
			
		||||
                        type_name: component.type_name().to_string(),
 | 
			
		||||
                let type_info = component.get_represented_type_info().ok_or_else(|| {
 | 
			
		||||
                    SceneSpawnError::NoRepresentedType {
 | 
			
		||||
                        type_path: component.reflect_type_path().to_string(),
 | 
			
		||||
                    }
 | 
			
		||||
                })?;
 | 
			
		||||
                let registration = type_registry.get(type_info.type_id()).ok_or_else(|| {
 | 
			
		||||
                    SceneSpawnError::UnregisteredButReflectedType {
 | 
			
		||||
                        type_path: type_info.type_path().to_string(),
 | 
			
		||||
                    }
 | 
			
		||||
                })?;
 | 
			
		||||
                let reflect_component =
 | 
			
		||||
                    registration.data::<ReflectComponent>().ok_or_else(|| {
 | 
			
		||||
                        SceneSpawnError::UnregisteredComponent {
 | 
			
		||||
                            type_name: component.type_name().to_string(),
 | 
			
		||||
                            type_path: type_info.type_path().to_string(),
 | 
			
		||||
                        }
 | 
			
		||||
                    })?;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -82,11 +82,11 @@ impl Scene {
 | 
			
		||||
                type_registry
 | 
			
		||||
                    .get(type_id)
 | 
			
		||||
                    .ok_or_else(|| SceneSpawnError::UnregisteredType {
 | 
			
		||||
                        type_name: component_info.name().to_string(),
 | 
			
		||||
                        std_type_name: component_info.name().to_string(),
 | 
			
		||||
                    })?;
 | 
			
		||||
            let reflect_resource = registration.data::<ReflectResource>().ok_or_else(|| {
 | 
			
		||||
                SceneSpawnError::UnregisteredResource {
 | 
			
		||||
                    type_name: component_info.name().to_string(),
 | 
			
		||||
                    type_path: registration.type_info().type_path().to_string(),
 | 
			
		||||
                }
 | 
			
		||||
            })?;
 | 
			
		||||
            reflect_resource.copy(&self.world, world);
 | 
			
		||||
@ -108,12 +108,12 @@ impl Scene {
 | 
			
		||||
                    let reflect_component = type_registry
 | 
			
		||||
                        .get(component_info.type_id().unwrap())
 | 
			
		||||
                        .ok_or_else(|| SceneSpawnError::UnregisteredType {
 | 
			
		||||
                            type_name: component_info.name().to_string(),
 | 
			
		||||
                            std_type_name: component_info.name().to_string(),
 | 
			
		||||
                        })
 | 
			
		||||
                        .and_then(|registration| {
 | 
			
		||||
                            registration.data::<ReflectComponent>().ok_or_else(|| {
 | 
			
		||||
                                SceneSpawnError::UnregisteredComponent {
 | 
			
		||||
                                    type_name: component_info.name().to_string(),
 | 
			
		||||
                                    type_path: registration.type_info().type_path().to_string(),
 | 
			
		||||
                                }
 | 
			
		||||
                            })
 | 
			
		||||
                        })?;
 | 
			
		||||
 | 
			
		||||
@ -74,22 +74,42 @@ pub struct SceneSpawner {
 | 
			
		||||
#[derive(Error, Debug)]
 | 
			
		||||
pub enum SceneSpawnError {
 | 
			
		||||
    /// Scene contains an unregistered component type.
 | 
			
		||||
    #[error("scene contains the unregistered component `{type_name}`. consider adding `#[reflect(Component)]` to your type")]
 | 
			
		||||
    #[error("scene contains the unregistered component `{type_path}`. consider adding `#[reflect(Component)]` to your type")]
 | 
			
		||||
    UnregisteredComponent {
 | 
			
		||||
        /// Type of the unregistered component.
 | 
			
		||||
        type_name: String,
 | 
			
		||||
        type_path: String,
 | 
			
		||||
    },
 | 
			
		||||
    /// Scene contains an unregistered resource type.
 | 
			
		||||
    #[error("scene contains the unregistered resource `{type_name}`. consider adding `#[reflect(Resource)]` to your type")]
 | 
			
		||||
    #[error("scene contains the unregistered resource `{type_path}`. consider adding `#[reflect(Resource)]` to your type")]
 | 
			
		||||
    UnregisteredResource {
 | 
			
		||||
        /// Type of the unregistered resource.
 | 
			
		||||
        type_name: String,
 | 
			
		||||
        type_path: String,
 | 
			
		||||
    },
 | 
			
		||||
    /// Scene contains an unregistered type.
 | 
			
		||||
    #[error("scene contains the unregistered type `{type_name}`. consider registering the type using `app.register_type::<T>()`")]
 | 
			
		||||
    #[error(
 | 
			
		||||
        "scene contains the unregistered type `{std_type_name}`. \
 | 
			
		||||
        consider reflecting it with `#[derive(Reflect)]` \
 | 
			
		||||
        and registering the type using `app.register_type::<T>()`"
 | 
			
		||||
    )]
 | 
			
		||||
    UnregisteredType {
 | 
			
		||||
        /// The [type name] for the unregistered type.
 | 
			
		||||
        /// [type name]: std::any::type_name
 | 
			
		||||
        std_type_name: String,
 | 
			
		||||
    },
 | 
			
		||||
    /// Scene contains an unregistered type which has a `TypePath`.
 | 
			
		||||
    #[error(
 | 
			
		||||
        "scene contains the reflected type `{type_path}` but it was not found in the type registry. \
 | 
			
		||||
        consider registering the type using `app.register_type::<T>()``"
 | 
			
		||||
    )]
 | 
			
		||||
    UnregisteredButReflectedType {
 | 
			
		||||
        /// The unregistered type.
 | 
			
		||||
        type_name: String,
 | 
			
		||||
        type_path: String,
 | 
			
		||||
    },
 | 
			
		||||
    /// Scene contains a proxy without a represented type.
 | 
			
		||||
    #[error("scene contains dynamic type `{type_path}` without a represented type. consider changing this using `set_represented_type`.")]
 | 
			
		||||
    NoRepresentedType {
 | 
			
		||||
        /// The dynamic instance type.
 | 
			
		||||
        type_path: String,
 | 
			
		||||
    },
 | 
			
		||||
    /// Dynamic scene with the given id does not exist.
 | 
			
		||||
    #[error("scene does not exist")]
 | 
			
		||||
 | 
			
		||||
@ -181,7 +181,7 @@ impl<'a> Serialize for SceneMapSerializer<'a> {
 | 
			
		||||
        let mut state = serializer.serialize_map(Some(self.entries.len()))?;
 | 
			
		||||
        for reflect in self.entries {
 | 
			
		||||
            state.serialize_entry(
 | 
			
		||||
                reflect.type_name(),
 | 
			
		||||
                reflect.get_represented_type_info().unwrap().type_path(),
 | 
			
		||||
                &TypedReflectSerializer::new(&**reflect, &self.registry.read()),
 | 
			
		||||
            )?;
 | 
			
		||||
        }
 | 
			
		||||
@ -467,7 +467,7 @@ impl<'a, 'de> Visitor<'de> for SceneMapVisitor<'a> {
 | 
			
		||||
            if !added.insert(registration.type_id()) {
 | 
			
		||||
                return Err(Error::custom(format_args!(
 | 
			
		||||
                    "duplicate reflect type: `{}`",
 | 
			
		||||
                    registration.type_name()
 | 
			
		||||
                    registration.type_info().type_path(),
 | 
			
		||||
                )));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -887,9 +887,15 @@ mod tests {
 | 
			
		||||
                let received = received
 | 
			
		||||
                    .components
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .find(|component| component.type_name() == expected.type_name())
 | 
			
		||||
                    .find(|component| {
 | 
			
		||||
                        component.get_represented_type_info().unwrap().type_path()
 | 
			
		||||
                            == expected.get_represented_type_info().unwrap().type_path()
 | 
			
		||||
                    })
 | 
			
		||||
                    .unwrap_or_else(|| {
 | 
			
		||||
                        panic!("missing component (expected: `{}`)", expected.type_name())
 | 
			
		||||
                        panic!(
 | 
			
		||||
                            "missing component (expected: `{}`)",
 | 
			
		||||
                            expected.get_represented_type_info().unwrap().type_path()
 | 
			
		||||
                        )
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                assert!(
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,10 @@ fn setup(type_registry: Res<AppTypeRegistry>) {
 | 
			
		||||
    let type_registry = type_registry.read();
 | 
			
		||||
 | 
			
		||||
    let registration = type_registry.get(TypeId::of::<MyType<u32>>()).unwrap();
 | 
			
		||||
    info!("Registration for {} exists", registration.short_name());
 | 
			
		||||
    info!(
 | 
			
		||||
        "Registration for {} exists",
 | 
			
		||||
        registration.type_info().type_path(),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // MyType<String> was not manually registered, so it does not exist
 | 
			
		||||
    assert!(type_registry.get(TypeId::of::<MyType<String>>()).is_none());
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user