Skip to main content

bevy_asset/
handle.rs

1use crate::{
2    meta::MetaTransform, Asset, AssetId, AssetIndex, AssetIndexAllocator, AssetPath, AssetServer,
3    Assets, ErasedAssetIndex, ReflectHandle, UntypedAssetId,
4};
5use alloc::sync::Arc;
6use bevy_ecs::template::{FromTemplate, SpecializeFromTemplate, Template, TemplateContext};
7use bevy_platform::{collections::Equivalent, sync::Mutex};
8use bevy_reflect::{enums::Enum, FromReflect, PartialReflect, Reflect, ReflectRef, TypePath};
9use core::{
10    any::TypeId,
11    hash::{Hash, Hasher},
12    marker::PhantomData,
13};
14use crossbeam_channel::{Receiver, Sender};
15use disqualified::ShortName;
16use thiserror::Error;
17use uuid::Uuid;
18
19/// Provides [`Handle`] and [`UntypedHandle`] _for a specific asset type_.
20/// This should _only_ be used for one specific asset type.
21#[derive(#[automatically_derived]
impl ::core::clone::Clone for AssetHandleProvider {
    #[inline]
    fn clone(&self) -> AssetHandleProvider {
        AssetHandleProvider {
            allocator: ::core::clone::Clone::clone(&self.allocator),
            drop_sender: ::core::clone::Clone::clone(&self.drop_sender),
            drop_receiver: ::core::clone::Clone::clone(&self.drop_receiver),
            type_id: ::core::clone::Clone::clone(&self.type_id),
        }
    }
}Clone)]
22pub struct AssetHandleProvider {
23    pub(crate) allocator: Arc<AssetIndexAllocator>,
24    pub(crate) drop_sender: Sender<DropEvent>,
25    pub(crate) drop_receiver: Receiver<DropEvent>,
26    pub(crate) type_id: TypeId,
27}
28
29#[derive(#[automatically_derived]
impl ::core::fmt::Debug for DropEvent {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "DropEvent",
            "index", &self.index, "asset_server_managed",
            &&self.asset_server_managed)
    }
}Debug)]
30pub(crate) struct DropEvent {
31    pub(crate) index: ErasedAssetIndex,
32    pub(crate) asset_server_managed: bool,
33}
34
35impl AssetHandleProvider {
36    pub(crate) fn new(type_id: TypeId, allocator: Arc<AssetIndexAllocator>) -> Self {
37        let (drop_sender, drop_receiver) = crossbeam_channel::unbounded();
38        Self {
39            type_id,
40            allocator,
41            drop_sender,
42            drop_receiver,
43        }
44    }
45
46    /// Reserves a new strong [`UntypedHandle`] (with a new [`UntypedAssetId`]). The stored [`Asset`] [`TypeId`] in the
47    /// [`UntypedHandle`] will match the [`Asset`] [`TypeId`] assigned to this [`AssetHandleProvider`].
48    pub fn reserve_handle(&self) -> UntypedHandle {
49        let index = self.allocator.reserve();
50        UntypedHandle::Strong(self.get_handle(index, false, None, None))
51    }
52
53    pub(crate) fn get_handle(
54        &self,
55        index: AssetIndex,
56        asset_server_managed: bool,
57        path: Option<AssetPath<'static>>,
58        meta_transform: Option<MetaTransform>,
59    ) -> Arc<StrongHandle> {
60        Arc::new(StrongHandle {
61            index,
62            type_id: self.type_id,
63            drop_sender: self.drop_sender.clone(),
64            meta_transform,
65            path,
66            asset_server_managed,
67        })
68    }
69
70    pub(crate) fn reserve_handle_internal(
71        &self,
72        asset_server_managed: bool,
73        path: Option<AssetPath<'static>>,
74        meta_transform: Option<MetaTransform>,
75    ) -> Arc<StrongHandle> {
76        let index = self.allocator.reserve();
77        self.get_handle(index, asset_server_managed, path, meta_transform)
78    }
79}
80
81/// The internal "strong" [`Asset`] handle storage for [`Handle::Strong`] and [`UntypedHandle::Strong`]. When this is dropped,
82/// the [`Asset`] will be freed. It also stores some asset metadata for easy access from handles.
83#[derive(const _: () =
    {
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for StrongHandle where  {
            fn type_path() -> &'static str {
                "bevy_asset::handle::StrongHandle"
            }
            fn short_type_path() -> &'static str { "StrongHandle" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("StrongHandle")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_asset::handle".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_asset::handle")
            }
        }
    };TypePath)]
84pub struct StrongHandle {
85    pub(crate) index: AssetIndex,
86    pub(crate) type_id: TypeId,
87    pub(crate) asset_server_managed: bool,
88    pub(crate) path: Option<AssetPath<'static>>,
89    /// Modifies asset meta. This is stored on the handle because it is:
90    /// 1. configuration tied to the lifetime of a specific asset load
91    /// 2. configuration that must be repeatable when the asset is hot-reloaded
92    pub(crate) meta_transform: Option<MetaTransform>,
93    pub(crate) drop_sender: Sender<DropEvent>,
94}
95
96impl Drop for StrongHandle {
97    fn drop(&mut self) {
98        let _ = self.drop_sender.send(DropEvent {
99            index: ErasedAssetIndex::new(self.index, self.type_id),
100            asset_server_managed: self.asset_server_managed,
101        });
102    }
103}
104
105impl core::fmt::Debug for StrongHandle {
106    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
107        f.debug_struct("StrongHandle")
108            .field("index", &self.index)
109            .field("type_id", &self.type_id)
110            .field("asset_server_managed", &self.asset_server_managed)
111            .field("path", &self.path)
112            .field("drop_sender", &self.drop_sender)
113            .finish()
114    }
115}
116
117/// A handle to a specific [`Asset`] of type `A`. Handles act as abstract "references" to
118/// assets, whose data are stored in the [`Assets<A>`] resource,
119/// avoiding the need to store multiple copies of the same data.
120///
121/// If a [`Handle`] is [`Handle::Strong`], the [`Asset`] will be kept
122/// alive until the [`Handle`] is dropped. If a [`Handle`] is [`Handle::Uuid`], it does not necessarily reference a live [`Asset`],
123/// nor will it keep assets alive.
124///
125/// Modifying a *handle* will change which existing asset is referenced, but modifying the *asset*
126/// (by mutating the [`Assets`] resource) will change the asset for all handles referencing it.
127///
128/// [`Handle`] can be cloned. If a [`Handle::Strong`] is cloned, the referenced [`Asset`] will not be freed until _all_ instances
129/// of the [`Handle`] are dropped.
130///
131/// [`Handle::Strong`], via [`StrongHandle`] also provides access to useful [`Asset`] metadata, such as the [`AssetPath`] (if it exists).
132#[derive(const _: () =
    {
        impl<A: Asset> bevy_reflect::GetTypeRegistration for Handle<A> where
            Handle<A>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, A: bevy_reflect::TypePath {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.register_type_data::<ReflectHandle, Self>();
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <Arc<StrongHandle> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Uuid as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl<A: Asset> bevy_reflect::Typed for Handle<A> where
            Handle<A>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, A: bevy_reflect::TypePath {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::GenericTypeInfoCell =
                    bevy_reflect::utility::GenericTypeInfoCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Strong",
                                                            &[bevy_reflect::UnnamedField::new::<Arc<StrongHandle>>(0usize)])),
                                                    bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Uuid",
                                                            &[bevy_reflect::UnnamedField::new::<Uuid>(0usize)]))]).with_generics(bevy_reflect::Generics::from_iter([bevy_reflect::GenericInfo::Type(bevy_reflect::TypeParamInfo::new::<A>(bevy_reflect::__macro_exports::alloc_utils::Cow::Borrowed("A")))])))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl<A: Asset> bevy_reflect::TypePath for Handle<A> where
            Handle<A>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, A: bevy_reflect::TypePath {
            fn type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("bevy_asset::handle::Handle<"),
                                    <A as bevy_reflect::TypePath>::type_path()), ">")
                        })
            }
            fn short_type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("Handle<"),
                                    <A as bevy_reflect::TypePath>::short_type_path()), ">")
                        })
            }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("Handle")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_asset::handle".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_asset::handle")
            }
        }
        impl<A: Asset> bevy_reflect::Reflect for Handle<A> where
            Handle<A>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, A: bevy_reflect::TypePath {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        impl<A: Asset> bevy_reflect::enums::Enum for Handle<A> where
            Handle<A>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, A: bevy_reflect::TypePath {
            fn field(&self, __name_param: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at(&self, __index_param: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self {
                    Handle::Strong { 0: __value, .. } if __index_param == 0usize
                        => ::core::option::Option::Some(__value),
                    Handle::Uuid { 0: __value, .. } if __index_param == 0usize
                        => ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, __name_param: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at_mut(&mut self, __index_param: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self {
                    Handle::Strong { 0: __value, .. } if __index_param == 0usize
                        => ::core::option::Option::Some(__value),
                    Handle::Uuid { 0: __value, .. } if __index_param == 0usize
                        => ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of(&self, __name_param: &str)
                -> ::core::option::Option<usize> {
                match self { _ => ::core::option::Option::None, }
            }
            fn name_at(&self, __index_param: usize)
                -> ::core::option::Option<&str> {
                match self { _ => ::core::option::Option::None, }
            }
            fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
                bevy_reflect::enums::VariantFieldIter::new(self)
            }
            #[inline]
            fn field_len(&self) -> usize {
                match self {
                    Handle::Strong { .. } => 1usize,
                    Handle::Uuid { .. } => 1usize,
                    _ => 0,
                }
            }
            #[inline]
            fn variant_name(&self) -> &str {
                match self {
                    Handle::Strong { .. } => "Strong",
                    Handle::Uuid { .. } => "Uuid",
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_index(&self) -> usize {
                match self {
                    Handle::Strong { .. } => 0usize,
                    Handle::Uuid { .. } => 1usize,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_type(&self) -> bevy_reflect::enums::VariantType {
                match self {
                    Handle::Strong { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    Handle::Uuid { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            fn to_dynamic_enum(&self) -> bevy_reflect::enums::DynamicEnum {
                bevy_reflect::enums::DynamicEnum::from_ref::<Self>(self)
            }
        }
        impl<A: Asset> bevy_reflect::PartialReflect for Handle<A> where
            Handle<A>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, A: bevy_reflect::TypePath {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self,
                __value_param: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Enum(__value_param) =
                        bevy_reflect::PartialReflect::reflect_ref(__value_param) {
                    if bevy_reflect::enums::Enum::variant_name(self) ==
                            bevy_reflect::enums::Enum::variant_name(__value_param) {
                        match bevy_reflect::enums::Enum::variant_type(__value_param)
                            {
                            bevy_reflect::enums::VariantType::Struct => {
                                for field in
                                    bevy_reflect::enums::Enum::iter_fields(__value_param) {
                                    let name = field.name().unwrap();
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_mut(self, name) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            bevy_reflect::enums::VariantType::Tuple => {
                                for (index, field) in
                                    ::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
                                    {
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_at_mut(self, index) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            _ => {}
                        }
                    } else {
                        match bevy_reflect::enums::Enum::variant_name(__value_param)
                            {
                            "Strong" => {
                                *self =
                                    Handle::Strong {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Strong"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <Arc<StrongHandle> as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<Arc<StrongHandle> as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "Uuid" => {
                                *self =
                                    Handle::Uuid {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Uuid"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <Uuid as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<Uuid as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                        1: ::core::default::Default::default(),
                                    }
                            }
                            name => {
                                return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
                                            enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
                                            variant_name: ::core::convert::Into::into(name),
                                        });
                            }
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
                                to_kind: bevy_reflect::ReflectKind::Enum,
                            });
                }
                ::core::result::Result::Ok(())
            }
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Enum
            }
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Enum(self)
            }
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Enum(self)
            }
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Enum(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_hash(&self) -> ::core::option::Option<u64> {
                use ::core::hash::{Hash, Hasher};
                let mut hasher = bevy_reflect::utility::reflect_hasher();
                Hash::hash(&::core::any::Any::type_id(self), &mut hasher);
                Hash::hash(self, &mut hasher);
                ::core::option::Option::Some(Hasher::finish(&hasher))
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                let value =
                    <dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
                if let ::core::option::Option::Some(value) = value {
                    ::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
                            value))
                } else { ::core::option::Option::Some(false) }
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::enums::enum_partial_cmp)(self, value)
            }
            fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
                -> ::core::fmt::Result {
                ::core::fmt::Debug::fmt(self, f)
            }
            #[inline]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
            }
        }
    };Reflect)]
133#[reflect(Debug, Hash, PartialEq, Clone, Handle, from_reflect = false)]
134pub enum Handle<A: Asset> {
135    /// A "strong" reference to a live (or loading) [`Asset`]. If a [`Handle`] is [`Handle::Strong`], the [`Asset`] will be kept
136    /// alive until the [`Handle`] is dropped. Strong handles also provide access to additional asset metadata.
137    Strong(Arc<StrongHandle>),
138    /// A reference to an [`Asset`] using a stable-across-runs / const identifier. Dropping this
139    /// handle will not result in the asset being dropped.
140    Uuid(Uuid, #[reflect(ignore, clone)] PhantomData<fn() -> A>),
141}
142
143// `Handle` needs a custom `FromReflect` to do extra type checking - see the
144// `strong_handle.type_id` check below.
145// `Handle` needs a custom `FromReflect` to do extra type checking - see the
146// `strong_handle.type_id` check below.
147impl<A: Asset> FromReflect for Handle<A>
148where
149    Handle<A>: Send + Sync,
150    A: TypePath,
151{
152    fn from_reflect(reflect_value: &dyn PartialReflect) -> Option<Self> {
153        let ReflectRef::Enum(enum_value) = PartialReflect::reflect_ref(reflect_value) else {
154            return None;
155        };
156
157        match Enum::variant_name(enum_value) {
158            "Strong" => {
159                let strong_field = enum_value.field_at(0usize)?;
160                let strong_handle = Arc::<StrongHandle>::from_reflect(strong_field)?;
161
162                // This is necessary as otherwise you could construct Handle<A> via Handle<B>
163                if strong_handle.type_id != TypeId::of::<A>() {
164                    return None;
165                }
166
167                Some(Handle::Strong(strong_handle))
168            }
169            "Uuid" => {
170                let uuid_field = enum_value.field_at(0usize)?;
171                let uuid = Uuid::from_reflect(uuid_field)?;
172
173                Some(Handle::Uuid(uuid, Default::default()))
174            }
175            _ => None,
176        }
177    }
178}
179
180impl<T: Asset> Clone for Handle<T> {
181    fn clone(&self) -> Self {
182        match self {
183            Handle::Strong(handle) => Handle::Strong(handle.clone()),
184            Handle::Uuid(uuid, ..) => Handle::Uuid(*uuid, PhantomData),
185        }
186    }
187}
188
189impl<A: Asset> Handle<A> {
190    /// Returns the [`AssetId`] of this [`Asset`].
191    #[inline]
192    pub fn id(&self) -> AssetId<A> {
193        match self {
194            Handle::Strong(handle) => AssetId::Index {
195                index: handle.index,
196                marker: PhantomData,
197            },
198            Handle::Uuid(uuid, ..) => AssetId::Uuid { uuid: *uuid },
199        }
200    }
201
202    /// Returns the path if this is (1) a strong handle and (2) the asset has a path
203    #[inline]
204    pub fn path(&self) -> Option<&AssetPath<'static>> {
205        match self {
206            Handle::Strong(handle) => handle.path.as_ref(),
207            Handle::Uuid(..) => None,
208        }
209    }
210
211    /// Returns `true` if this is a uuid handle.
212    #[inline]
213    pub fn is_uuid(&self) -> bool {
214        #[allow(non_exhaustive_omitted_patterns)] match self {
    Handle::Uuid(..) => true,
    _ => false,
}matches!(self, Handle::Uuid(..))
215    }
216
217    /// Returns `true` if this is a strong handle.
218    #[inline]
219    pub fn is_strong(&self) -> bool {
220        #[allow(non_exhaustive_omitted_patterns)] match self {
    Handle::Strong(_) => true,
    _ => false,
}matches!(self, Handle::Strong(_))
221    }
222
223    /// Converts this [`Handle`] to an "untyped" / "generic-less" [`UntypedHandle`], which stores the [`Asset`] type information
224    /// _inside_ [`UntypedHandle`]. This will return [`UntypedHandle::Strong`] for [`Handle::Strong`] and [`UntypedHandle::Uuid`] for
225    /// [`Handle::Uuid`].
226    #[inline]
227    pub fn untyped(self) -> UntypedHandle {
228        self.into()
229    }
230}
231
232impl<A: Asset> Default for Handle<A> {
233    fn default() -> Self {
234        Handle::Uuid(AssetId::<A>::DEFAULT_UUID, PhantomData)
235    }
236}
237
238// This enables FromTemplate specialization for `Handle<T>` using the
239// ["auto trait specialization" trick](https://github.com/coolcatcoder/rust_techniques/issues/1)
240// This enables Handle to implement Default _and_ implement FromTemplate, without conflicting with the
241// blanket impl of FromTemplate for T: Default + Clone.
242impl<T: Asset> Unpin for Handle<T> where for<'a> [()]: SpecializeFromTemplate {}
243
244impl<T: Asset> FromTemplate for Handle<T> {
245    type Template = HandleTemplate<T>;
246}
247
248/// A [`Template`] that produces a [`Handle`].
249///
250/// # How asset paths are resolved in templates
251///
252/// When a type with a [`Handle<T>`] field derives [`FromTemplate`], that field is replaced by its
253/// template type, [`HandleTemplate<T>`], when created via BSN.
254/// We can see that [`HandleTemplate<T>`] has the following trait impl block:
255///
256/// ```rust, ignore
257/// impl<I: Into<AssetPath<'static>>, T: Asset> From<I> for HandleTemplate<T> {
258///     fn from(value: I) -> Self {
259///         Self::Path(value.into())
260///     }
261/// }
262/// ```
263///
264/// [`AssetPath<'static>`] implements [`From<&'static str>`].
265/// Because of that, assigning a string literal to a `Handle<T>` field automatically converts it into
266/// [`HandleTemplate<T>::Path`] with that asset path when used in the `bsn!` macro.
267/// Calls to `bsn!` automatically insert `.into()` conversions, and due to Rust's blanket impl that turns [`From`] trait impls into their [`Into`]
268/// equivalents, the conversion from `&'static str` to `AssetPath<'static>` is handled automatically.
269/// Finally, the [`HandleTemplate<T>::Path`] generated gets converted to a [`Handle<T>`] during scene initialization,
270/// as the asset is loaded from the given path, and the resulting handle is assigned to the field,
271/// pointing to the asset that was found at the file path in our original string.
272#[derive(const _: () =
    {
        impl<T: Asset> bevy_reflect::GetTypeRegistration for HandleTemplate<T>
            where HandleTemplate<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Handle<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection,
            ArcMutexValue<T>: bevy_reflect::FromReflect +
            bevy_reflect::TypePath + bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <AssetPath<'static> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Handle<T> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <ArcMutexValue<T> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl<T: Asset> bevy_reflect::Typed for HandleTemplate<T> where
            HandleTemplate<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Handle<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection,
            ArcMutexValue<T>: bevy_reflect::FromReflect +
            bevy_reflect::TypePath + bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::GenericTypeInfoCell =
                    bevy_reflect::utility::GenericTypeInfoCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Path",
                                                            &[bevy_reflect::UnnamedField::new::<AssetPath<'static>>(0usize)])),
                                                    bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Handle",
                                                            &[bevy_reflect::UnnamedField::new::<Handle<T>>(0usize)])),
                                                    bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Value",
                                                            &[bevy_reflect::UnnamedField::new::<ArcMutexValue<T>>(0usize)]))]).with_generics(bevy_reflect::Generics::from_iter([bevy_reflect::GenericInfo::Type(bevy_reflect::TypeParamInfo::new::<T>(bevy_reflect::__macro_exports::alloc_utils::Cow::Borrowed("T")))])))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl<T: Asset> bevy_reflect::TypePath for HandleTemplate<T> where
            HandleTemplate<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath {
            fn type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("bevy_asset::handle::HandleTemplate<"),
                                    <T as bevy_reflect::TypePath>::type_path()), ">")
                        })
            }
            fn short_type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("HandleTemplate<"),
                                    <T as bevy_reflect::TypePath>::short_type_path()), ">")
                        })
            }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("HandleTemplate")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_asset::handle".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_asset::handle")
            }
        }
        impl<T: Asset> bevy_reflect::Reflect for HandleTemplate<T> where
            HandleTemplate<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Handle<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection,
            ArcMutexValue<T>: bevy_reflect::FromReflect +
            bevy_reflect::TypePath + bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        impl<T: Asset> bevy_reflect::enums::Enum for HandleTemplate<T> where
            HandleTemplate<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Handle<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection,
            ArcMutexValue<T>: bevy_reflect::FromReflect +
            bevy_reflect::TypePath + bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn field(&self, __name_param: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at(&self, __index_param: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self {
                    HandleTemplate::Path { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    HandleTemplate::Handle { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    HandleTemplate::Value { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, __name_param: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at_mut(&mut self, __index_param: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self {
                    HandleTemplate::Path { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    HandleTemplate::Handle { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    HandleTemplate::Value { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of(&self, __name_param: &str)
                -> ::core::option::Option<usize> {
                match self { _ => ::core::option::Option::None, }
            }
            fn name_at(&self, __index_param: usize)
                -> ::core::option::Option<&str> {
                match self { _ => ::core::option::Option::None, }
            }
            fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
                bevy_reflect::enums::VariantFieldIter::new(self)
            }
            #[inline]
            fn field_len(&self) -> usize {
                match self {
                    HandleTemplate::Path { .. } => 1usize,
                    HandleTemplate::Handle { .. } => 1usize,
                    HandleTemplate::Value { .. } => 1usize,
                    _ => 0,
                }
            }
            #[inline]
            fn variant_name(&self) -> &str {
                match self {
                    HandleTemplate::Path { .. } => "Path",
                    HandleTemplate::Handle { .. } => "Handle",
                    HandleTemplate::Value { .. } => "Value",
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_index(&self) -> usize {
                match self {
                    HandleTemplate::Path { .. } => 0usize,
                    HandleTemplate::Handle { .. } => 1usize,
                    HandleTemplate::Value { .. } => 2usize,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_type(&self) -> bevy_reflect::enums::VariantType {
                match self {
                    HandleTemplate::Path { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    HandleTemplate::Handle { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    HandleTemplate::Value { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            fn to_dynamic_enum(&self) -> bevy_reflect::enums::DynamicEnum {
                bevy_reflect::enums::DynamicEnum::from_ref::<Self>(self)
            }
        }
        impl<T: Asset> bevy_reflect::PartialReflect for HandleTemplate<T>
            where HandleTemplate<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Handle<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection,
            ArcMutexValue<T>: bevy_reflect::FromReflect +
            bevy_reflect::TypePath + bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self,
                __value_param: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Enum(__value_param) =
                        bevy_reflect::PartialReflect::reflect_ref(__value_param) {
                    if bevy_reflect::enums::Enum::variant_name(self) ==
                            bevy_reflect::enums::Enum::variant_name(__value_param) {
                        match bevy_reflect::enums::Enum::variant_type(__value_param)
                            {
                            bevy_reflect::enums::VariantType::Struct => {
                                for field in
                                    bevy_reflect::enums::Enum::iter_fields(__value_param) {
                                    let name = field.name().unwrap();
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_mut(self, name) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            bevy_reflect::enums::VariantType::Tuple => {
                                for (index, field) in
                                    ::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
                                    {
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_at_mut(self, index) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            _ => {}
                        }
                    } else {
                        match bevy_reflect::enums::Enum::variant_name(__value_param)
                            {
                            "Path" => {
                                *self =
                                    HandleTemplate::Path {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Path"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <AssetPath<'static> as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<AssetPath<'static> as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "Handle" => {
                                *self =
                                    HandleTemplate::Handle {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Handle"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <Handle<T> as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<Handle<T> as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "Value" => {
                                *self =
                                    HandleTemplate::Value {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Value"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <ArcMutexValue<T> as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<ArcMutexValue<T> as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            name => {
                                return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
                                            enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
                                            variant_name: ::core::convert::Into::into(name),
                                        });
                            }
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
                                to_kind: bevy_reflect::ReflectKind::Enum,
                            });
                }
                ::core::result::Result::Ok(())
            }
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Enum
            }
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Enum(self)
            }
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Enum(self)
            }
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Enum(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_hash(&self) -> ::core::option::Option<u64> {
                (bevy_reflect::enums::enum_hash)(self)
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::enums::enum_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::enums::enum_partial_cmp)(self, value)
            }
            #[inline]
            #[allow(unreachable_code, reason =
            "Ignored fields without a `clone` attribute will early-return with an error")]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                let this = self;
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(match this
                            {
                            HandleTemplate::Path { 0: __0 } =>
                                HandleTemplate::Path {
                                    0: <AssetPath<'static> as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__0)?,
                                },
                            HandleTemplate::Handle { 0: __0 } =>
                                HandleTemplate::Handle {
                                    0: <Handle<T> as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__0)?,
                                },
                            HandleTemplate::Value { 0: __0 } =>
                                HandleTemplate::Value {
                                    0: <ArcMutexValue<T> as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__0)?,
                                },
                        }))
            }
        }
        impl<T: Asset> bevy_reflect::FromReflect for HandleTemplate<T> where
            HandleTemplate<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Handle<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection,
            ArcMutexValue<T>: bevy_reflect::FromReflect +
            bevy_reflect::TypePath + bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn from_reflect(__param0: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Enum(__param0) =
                        bevy_reflect::PartialReflect::reflect_ref(__param0) {
                    match bevy_reflect::enums::Enum::variant_name(__param0) {
                        "Path" =>
                            ::core::option::Option::Some(HandleTemplate::Path {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <AssetPath<'static> as
                                                    bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        "Handle" =>
                            ::core::option::Option::Some(HandleTemplate::Handle {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <Handle<T> as bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        "Value" =>
                            ::core::option::Option::Some(HandleTemplate::Value {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <ArcMutexValue<T> as
                                                    bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        name => ::core::option::Option::None,
                    }
                } else { ::core::option::Option::None }
            }
        }
    };Reflect)]
273pub enum HandleTemplate<T: Asset> {
274    /// Creates a [`Handle`] by calling [`AssetServer::load`] on the given [`AssetPath`].
275    Path(AssetPath<'static>),
276    /// Creates a [`Handle`] by cloning the given [`Handle`] value.
277    Handle(Handle<T>),
278    /// Creates a [`Handle`] by adding the given asset value using [`AssetServer::add`]. This will
279    /// cache the resulting [`Handle`] on the template and reuse it for future template builds.
280    ///
281    /// This should generally be constructed using [`HandleTemplate::value`] or [`asset_value`].
282    Value(ArcMutexValue<T>),
283}
284
285impl<T: Asset> HandleTemplate<T> {
286    /// This will create a new [`HandleTemplate`] for the given `asset` value. This makes it possible
287    /// to define assets "inline" in templates / scenes that produce a [`Handle`].
288    ///
289    /// This supports [`Into`]
290    /// to automatically convert values that can become `A`.
291    pub fn value(value: impl Into<T>) -> Self {
292        HandleTemplate::Value(ArcMutexValue(Arc::new(Mutex::new(AssetOrHandle::Value(
293            Some(value.into()),
294        )))))
295    }
296}
297
298/// Stores an [`Arc<Mutex<AssetOrHandle<T>>>`].
299///
300/// This intermediary type exists largely to enable reflect(opaque).
301#[derive(const _: () =
    {
        impl<T: Asset> bevy_reflect::GetTypeRegistration for ArcMutexValue<T>
            where ArcMutexValue<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl<T: Asset> bevy_reflect::TypePath for ArcMutexValue<T> where
            ArcMutexValue<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath {
            fn type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("bevy_asset::handle::ArcMutexValue<"),
                                    <T as bevy_reflect::TypePath>::type_path()), ">")
                        })
            }
            fn short_type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("ArcMutexValue<"),
                                    <T as bevy_reflect::TypePath>::short_type_path()), ">")
                        })
            }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("ArcMutexValue")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_asset::handle".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_asset::handle")
            }
        }
        impl<T: Asset> bevy_reflect::Typed for ArcMutexValue<T> where
            ArcMutexValue<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::GenericTypeInfoCell =
                    bevy_reflect::utility::GenericTypeInfoCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            let info = bevy_reflect::OpaqueInfo::new::<Self>();
                            bevy_reflect::TypeInfo::Opaque(info)
                        })
            }
        }
        impl<T: Asset> bevy_reflect::Reflect for ArcMutexValue<T> where
            ArcMutexValue<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        impl<T: Asset> bevy_reflect::PartialReflect for ArcMutexValue<T> where
            ArcMutexValue<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn to_dynamic(&self)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self))
            }
            #[inline]
            fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let ::core::option::Option::Some(value) =
                        <dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value)
                    {
                    *self = ::core::clone::Clone::clone(value);
                    return ::core::result::Result::Ok(());
                }
                ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedTypes {
                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(value)),
                        to_type: ::core::convert::Into::into(<Self as
                                    bevy_reflect::TypePath>::type_path()),
                    })
            }
            #[inline]
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Opaque
            }
            #[inline]
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Opaque(self)
            }
            #[inline]
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Opaque(self)
            }
            #[inline]
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Opaque(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
        }
        impl<T: Asset> bevy_reflect::FromReflect for ArcMutexValue<T> where
            ArcMutexValue<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath {
            fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                ::core::option::Option::Some(::core::clone::Clone::clone(<dyn bevy_reflect::PartialReflect>::try_downcast_ref::<ArcMutexValue<T>>(reflect)?))
            }
        }
    };Reflect)]
302#[reflect(opaque)]
303pub struct ArcMutexValue<T: Asset>(Arc<Mutex<AssetOrHandle<T>>>);
304
305impl<T: Asset> Clone for ArcMutexValue<T> {
306    fn clone(&self) -> Self {
307        Self(self.0.clone())
308    }
309}
310
311#[derive(const _: () =
    {
        impl<T: Asset> bevy_reflect::GetTypeRegistration for AssetOrHandle<T>
            where AssetOrHandle<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Option<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection,
            Handle<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <Option<T> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Handle<T> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl<T: Asset> bevy_reflect::Typed for AssetOrHandle<T> where
            AssetOrHandle<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Option<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection,
            Handle<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::GenericTypeInfoCell =
                    bevy_reflect::utility::GenericTypeInfoCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Value",
                                                            &[bevy_reflect::UnnamedField::new::<Option<T>>(0usize)])),
                                                    bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Handle",
                                                            &[bevy_reflect::UnnamedField::new::<Handle<T>>(0usize)]))]).with_generics(bevy_reflect::Generics::from_iter([bevy_reflect::GenericInfo::Type(bevy_reflect::TypeParamInfo::new::<T>(bevy_reflect::__macro_exports::alloc_utils::Cow::Borrowed("T")))])))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl<T: Asset> bevy_reflect::TypePath for AssetOrHandle<T> where
            AssetOrHandle<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath {
            fn type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("bevy_asset::handle::AssetOrHandle<"),
                                    <T as bevy_reflect::TypePath>::type_path()), ">")
                        })
            }
            fn short_type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("AssetOrHandle<"),
                                    <T as bevy_reflect::TypePath>::short_type_path()), ">")
                        })
            }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("AssetOrHandle")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_asset::handle".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_asset::handle")
            }
        }
        impl<T: Asset> bevy_reflect::Reflect for AssetOrHandle<T> where
            AssetOrHandle<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Option<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection,
            Handle<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        impl<T: Asset> bevy_reflect::enums::Enum for AssetOrHandle<T> where
            AssetOrHandle<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Option<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection,
            Handle<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn field(&self, __name_param: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at(&self, __index_param: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self {
                    AssetOrHandle::Value { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    AssetOrHandle::Handle { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, __name_param: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at_mut(&mut self, __index_param: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self {
                    AssetOrHandle::Value { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    AssetOrHandle::Handle { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of(&self, __name_param: &str)
                -> ::core::option::Option<usize> {
                match self { _ => ::core::option::Option::None, }
            }
            fn name_at(&self, __index_param: usize)
                -> ::core::option::Option<&str> {
                match self { _ => ::core::option::Option::None, }
            }
            fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
                bevy_reflect::enums::VariantFieldIter::new(self)
            }
            #[inline]
            fn field_len(&self) -> usize {
                match self {
                    AssetOrHandle::Value { .. } => 1usize,
                    AssetOrHandle::Handle { .. } => 1usize,
                    _ => 0,
                }
            }
            #[inline]
            fn variant_name(&self) -> &str {
                match self {
                    AssetOrHandle::Value { .. } => "Value",
                    AssetOrHandle::Handle { .. } => "Handle",
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_index(&self) -> usize {
                match self {
                    AssetOrHandle::Value { .. } => 0usize,
                    AssetOrHandle::Handle { .. } => 1usize,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_type(&self) -> bevy_reflect::enums::VariantType {
                match self {
                    AssetOrHandle::Value { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    AssetOrHandle::Handle { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            fn to_dynamic_enum(&self) -> bevy_reflect::enums::DynamicEnum {
                bevy_reflect::enums::DynamicEnum::from_ref::<Self>(self)
            }
        }
        impl<T: Asset> bevy_reflect::PartialReflect for AssetOrHandle<T> where
            AssetOrHandle<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Option<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection,
            Handle<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self,
                __value_param: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Enum(__value_param) =
                        bevy_reflect::PartialReflect::reflect_ref(__value_param) {
                    if bevy_reflect::enums::Enum::variant_name(self) ==
                            bevy_reflect::enums::Enum::variant_name(__value_param) {
                        match bevy_reflect::enums::Enum::variant_type(__value_param)
                            {
                            bevy_reflect::enums::VariantType::Struct => {
                                for field in
                                    bevy_reflect::enums::Enum::iter_fields(__value_param) {
                                    let name = field.name().unwrap();
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_mut(self, name) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            bevy_reflect::enums::VariantType::Tuple => {
                                for (index, field) in
                                    ::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
                                    {
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_at_mut(self, index) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            _ => {}
                        }
                    } else {
                        match bevy_reflect::enums::Enum::variant_name(__value_param)
                            {
                            "Value" => {
                                *self =
                                    AssetOrHandle::Value {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Value"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <Option<T> as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<Option<T> as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "Handle" => {
                                *self =
                                    AssetOrHandle::Handle {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Handle"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <Handle<T> as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<Handle<T> as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            name => {
                                return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
                                            enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
                                            variant_name: ::core::convert::Into::into(name),
                                        });
                            }
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
                                to_kind: bevy_reflect::ReflectKind::Enum,
                            });
                }
                ::core::result::Result::Ok(())
            }
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Enum
            }
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Enum(self)
            }
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Enum(self)
            }
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Enum(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_hash(&self) -> ::core::option::Option<u64> {
                (bevy_reflect::enums::enum_hash)(self)
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::enums::enum_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::enums::enum_partial_cmp)(self, value)
            }
            #[inline]
            #[allow(unreachable_code, reason =
            "Ignored fields without a `clone` attribute will early-return with an error")]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                let this = self;
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(match this
                            {
                            AssetOrHandle::Value { 0: __0 } =>
                                AssetOrHandle::Value {
                                    0: <Option<T> as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__0)?,
                                },
                            AssetOrHandle::Handle { 0: __0 } =>
                                AssetOrHandle::Handle {
                                    0: <Handle<T> as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__0)?,
                                },
                        }))
            }
        }
        impl<T: Asset> bevy_reflect::FromReflect for AssetOrHandle<T> where
            AssetOrHandle<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Option<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection,
            Handle<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn from_reflect(__param0: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Enum(__param0) =
                        bevy_reflect::PartialReflect::reflect_ref(__param0) {
                    match bevy_reflect::enums::Enum::variant_name(__param0) {
                        "Value" =>
                            ::core::option::Option::Some(AssetOrHandle::Value {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <Option<T> as bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        "Handle" =>
                            ::core::option::Option::Some(AssetOrHandle::Handle {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <Handle<T> as bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        name => ::core::option::Option::None,
                    }
                } else { ::core::option::Option::None }
            }
        }
    };Reflect)]
312enum AssetOrHandle<T: Asset> {
313    Value(Option<T>),
314    Handle(Handle<T>),
315}
316
317impl<T: Asset> Default for AssetOrHandle<T> {
318    fn default() -> Self {
319        Self::Handle(Default::default())
320    }
321}
322
323impl<T: Asset> Default for HandleTemplate<T> {
324    fn default() -> Self {
325        Self::Handle(Default::default())
326    }
327}
328
329impl<I: Into<AssetPath<'static>>, T: Asset> From<I> for HandleTemplate<T> {
330    fn from(value: I) -> Self {
331        Self::Path(value.into())
332    }
333}
334
335impl<T: Asset> From<Handle<T>> for HandleTemplate<T> {
336    fn from(value: Handle<T>) -> Self {
337        Self::Handle(value)
338    }
339}
340
341impl<T: Asset> Template for HandleTemplate<T> {
342    type Output = Handle<T>;
343    fn build_template(&self, context: &mut TemplateContext) -> bevy_ecs::error::Result<Handle<T>> {
344        Ok(match self {
345            HandleTemplate::Path(asset_path) => context.resource::<AssetServer>().load(asset_path),
346            HandleTemplate::Handle(handle) => handle.clone(),
347            HandleTemplate::Value(value) => {
348                // This unwrap is ok. If another caller panicked while holding this mutex, then the
349                // program is in an invalid state and this should panic too.
350                let mut value_or_handle = value.0.lock().unwrap();
351                match &mut *value_or_handle {
352                    AssetOrHandle::Value(value) => {
353                        // This unwrap is ok because AssetOrHandle::Value will always either contain a Some Value
354                        // when it is in this state (AssetOrHandle is private).
355                        let handle = context
356                            .resource_mut::<Assets<T>>()
357                            .add(value.take().unwrap());
358                        *value_or_handle = AssetOrHandle::Handle(handle.clone());
359                        handle
360                    }
361                    AssetOrHandle::Handle(handle) => handle.clone(),
362                }
363            }
364        })
365    }
366
367    fn clone_template(&self) -> Self {
368        match self {
369            HandleTemplate::Path(asset_path) => HandleTemplate::Path(asset_path.clone()),
370            HandleTemplate::Handle(handle) => HandleTemplate::Handle(handle.clone()),
371            HandleTemplate::Value(value) => HandleTemplate::Value(value.clone()),
372        }
373    }
374}
375
376/// This will create a new [`HandleTemplate`] for the given `asset` value. This makes it possible
377/// to define assets "inline" in templates / scenes that produce a [`Handle`].
378///
379/// This supports [`Into`]
380/// to automatically convert values that can become `A`.
381pub fn asset_value<I: Into<A>, A: Asset>(asset: I) -> HandleTemplate<A> {
382    HandleTemplate::value(asset)
383}
384
385impl<A: Asset> core::fmt::Debug for Handle<A> {
386    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
387        let name = ShortName::of::<A>();
388        match self {
389            Handle::Strong(handle) => {
390                f.write_fmt(format_args!("StrongHandle<{3}>{{ index: {0:?}, type_id: {1:?}, path: {2:?} }}",
        handle.index, handle.type_id, handle.path, name))write!(
391                    f,
392                    "StrongHandle<{name}>{{ index: {:?}, type_id: {:?}, path: {:?} }}",
393                    handle.index, handle.type_id, handle.path
394                )
395            }
396            Handle::Uuid(uuid, ..) => f.write_fmt(format_args!("UuidHandle<{0}>({1:?})", name, uuid))write!(f, "UuidHandle<{name}>({uuid:?})"),
397        }
398    }
399}
400
401impl<A: Asset> Hash for Handle<A> {
402    #[inline]
403    fn hash<H: Hasher>(&self, state: &mut H) {
404        self.id().hash(state);
405    }
406}
407
408// Handle uses AssetId when hashing. This enables using AssetId instead of handle with hashsets and hashmaps.
409impl<T: Asset> Equivalent<Handle<T>> for AssetId<T> {
410    fn equivalent(&self, key: &Handle<T>) -> bool {
411        *self == key.id()
412    }
413}
414
415impl<A: Asset> PartialOrd for Handle<A> {
416    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
417        Some(self.cmp(other))
418    }
419}
420
421impl<A: Asset> Ord for Handle<A> {
422    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
423        self.id().cmp(&other.id())
424    }
425}
426
427impl<A: Asset> PartialEq for Handle<A> {
428    #[inline]
429    fn eq(&self, other: &Self) -> bool {
430        self.id() == other.id()
431    }
432}
433
434impl<A: Asset> Eq for Handle<A> {}
435
436impl<A: Asset> From<&Handle<A>> for AssetId<A> {
437    #[inline]
438    fn from(value: &Handle<A>) -> Self {
439        value.id()
440    }
441}
442
443impl<A: Asset> From<&Handle<A>> for UntypedAssetId {
444    #[inline]
445    fn from(value: &Handle<A>) -> Self {
446        value.id().into()
447    }
448}
449
450impl<A: Asset> From<&mut Handle<A>> for AssetId<A> {
451    #[inline]
452    fn from(value: &mut Handle<A>) -> Self {
453        value.id()
454    }
455}
456
457impl<A: Asset> From<&mut Handle<A>> for UntypedAssetId {
458    #[inline]
459    fn from(value: &mut Handle<A>) -> Self {
460        value.id().into()
461    }
462}
463
464impl<A: Asset> From<Uuid> for Handle<A> {
465    #[inline]
466    fn from(uuid: Uuid) -> Self {
467        Handle::Uuid(uuid, PhantomData)
468    }
469}
470
471/// An untyped variant of [`Handle`], which internally stores the [`Asset`] type information at runtime
472/// as a [`TypeId`] instead of encoding it in the compile-time type. This allows handles across [`Asset`] types
473/// to be stored together and compared.
474///
475/// See [`Handle`] for more information.
476#[derive(#[automatically_derived]
impl ::core::clone::Clone for UntypedHandle {
    #[inline]
    fn clone(&self) -> UntypedHandle {
        match self {
            UntypedHandle::Strong(__self_0) =>
                UntypedHandle::Strong(::core::clone::Clone::clone(__self_0)),
            UntypedHandle::Uuid { type_id: __self_0, uuid: __self_1 } =>
                UntypedHandle::Uuid {
                    type_id: ::core::clone::Clone::clone(__self_0),
                    uuid: ::core::clone::Clone::clone(__self_1),
                },
        }
    }
}Clone, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for UntypedHandle where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <Arc<StrongHandle> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <TypeId as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Uuid as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for UntypedHandle where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Strong",
                                                        &[bevy_reflect::UnnamedField::new::<Arc<StrongHandle>>(0usize)])),
                                                bevy_reflect::enums::VariantInfo::Struct(bevy_reflect::enums::StructVariantInfo::new("Uuid",
                                                        &[bevy_reflect::NamedField::new::<TypeId>("type_id"),
                                                                    bevy_reflect::NamedField::new::<Uuid>("uuid")]))]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for UntypedHandle where  {
            fn type_path() -> &'static str {
                "bevy_asset::handle::UntypedHandle"
            }
            fn short_type_path() -> &'static str { "UntypedHandle" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("UntypedHandle")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_asset::handle".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_asset::handle")
            }
        }
        impl bevy_reflect::Reflect for UntypedHandle where  {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        impl bevy_reflect::enums::Enum for UntypedHandle where  {
            fn field(&self, __name_param: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self {
                    UntypedHandle::Uuid { type_id: __value, .. } if
                        __name_param == "type_id" =>
                        ::core::option::Option::Some(__value),
                    UntypedHandle::Uuid { uuid: __value, .. } if
                        __name_param == "uuid" =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, __index_param: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self {
                    UntypedHandle::Strong { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    UntypedHandle::Uuid { type_id: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    UntypedHandle::Uuid { uuid: __value, .. } if
                        __index_param == 1usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, __name_param: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self {
                    UntypedHandle::Uuid { type_id: __value, .. } if
                        __name_param == "type_id" =>
                        ::core::option::Option::Some(__value),
                    UntypedHandle::Uuid { uuid: __value, .. } if
                        __name_param == "uuid" =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, __index_param: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self {
                    UntypedHandle::Strong { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    UntypedHandle::Uuid { type_id: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    UntypedHandle::Uuid { uuid: __value, .. } if
                        __index_param == 1usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of(&self, __name_param: &str)
                -> ::core::option::Option<usize> {
                match self {
                    UntypedHandle::Uuid { .. } if __name_param == "type_id" =>
                        ::core::option::Option::Some(0usize),
                    UntypedHandle::Uuid { .. } if __name_param == "uuid" =>
                        ::core::option::Option::Some(1usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, __index_param: usize)
                -> ::core::option::Option<&str> {
                match self {
                    UntypedHandle::Uuid { .. } if __index_param == 0usize =>
                        ::core::option::Option::Some("type_id"),
                    UntypedHandle::Uuid { .. } if __index_param == 1usize =>
                        ::core::option::Option::Some("uuid"),
                    _ => ::core::option::Option::None,
                }
            }
            fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
                bevy_reflect::enums::VariantFieldIter::new(self)
            }
            #[inline]
            fn field_len(&self) -> usize {
                match self {
                    UntypedHandle::Strong { .. } => 1usize,
                    UntypedHandle::Uuid { .. } => 2usize,
                    _ => 0,
                }
            }
            #[inline]
            fn variant_name(&self) -> &str {
                match self {
                    UntypedHandle::Strong { .. } => "Strong",
                    UntypedHandle::Uuid { .. } => "Uuid",
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_index(&self) -> usize {
                match self {
                    UntypedHandle::Strong { .. } => 0usize,
                    UntypedHandle::Uuid { .. } => 1usize,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_type(&self) -> bevy_reflect::enums::VariantType {
                match self {
                    UntypedHandle::Strong { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    UntypedHandle::Uuid { .. } =>
                        bevy_reflect::enums::VariantType::Struct,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            fn to_dynamic_enum(&self) -> bevy_reflect::enums::DynamicEnum {
                bevy_reflect::enums::DynamicEnum::from_ref::<Self>(self)
            }
        }
        impl bevy_reflect::PartialReflect for UntypedHandle where  {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self,
                __value_param: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Enum(__value_param) =
                        bevy_reflect::PartialReflect::reflect_ref(__value_param) {
                    if bevy_reflect::enums::Enum::variant_name(self) ==
                            bevy_reflect::enums::Enum::variant_name(__value_param) {
                        match bevy_reflect::enums::Enum::variant_type(__value_param)
                            {
                            bevy_reflect::enums::VariantType::Struct => {
                                for field in
                                    bevy_reflect::enums::Enum::iter_fields(__value_param) {
                                    let name = field.name().unwrap();
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_mut(self, name) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            bevy_reflect::enums::VariantType::Tuple => {
                                for (index, field) in
                                    ::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
                                    {
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_at_mut(self, index) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            _ => {}
                        }
                    } else {
                        match bevy_reflect::enums::Enum::variant_name(__value_param)
                            {
                            "Strong" => {
                                *self =
                                    UntypedHandle::Strong {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Strong"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <Arc<StrongHandle> as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<Arc<StrongHandle> as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "Uuid" => {
                                *self =
                                    UntypedHandle::Uuid {
                                        type_id: {
                                            let __type_id = __value_param.field("type_id");
                                            let __type_id =
                                                __type_id.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Uuid"),
                                                            field_name: ::core::convert::Into::into("type_id"),
                                                        })?;
                                            <TypeId as
                                                            bevy_reflect::FromReflect>::from_reflect(__type_id).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__type_id)),
                                                        to_type: ::core::convert::Into::into(<TypeId as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                        uuid: {
                                            let __uuid = __value_param.field("uuid");
                                            let __uuid =
                                                __uuid.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Uuid"),
                                                            field_name: ::core::convert::Into::into("uuid"),
                                                        })?;
                                            <Uuid as
                                                            bevy_reflect::FromReflect>::from_reflect(__uuid).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__uuid)),
                                                        to_type: ::core::convert::Into::into(<Uuid as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            name => {
                                return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
                                            enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
                                            variant_name: ::core::convert::Into::into(name),
                                        });
                            }
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
                                to_kind: bevy_reflect::ReflectKind::Enum,
                            });
                }
                ::core::result::Result::Ok(())
            }
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Enum
            }
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Enum(self)
            }
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Enum(self)
            }
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Enum(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_hash(&self) -> ::core::option::Option<u64> {
                (bevy_reflect::enums::enum_hash)(self)
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::enums::enum_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::enums::enum_partial_cmp)(self, value)
            }
            #[inline]
            #[allow(unreachable_code, reason =
            "Ignored fields without a `clone` attribute will early-return with an error")]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                let this = self;
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(match this
                            {
                            UntypedHandle::Strong { 0: __0 } =>
                                UntypedHandle::Strong {
                                    0: <Arc<StrongHandle> as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__0)?,
                                },
                            UntypedHandle::Uuid { type_id: __type_id, uuid: __uuid } =>
                                UntypedHandle::Uuid {
                                    type_id: <TypeId as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__type_id)?,
                                    uuid: <Uuid as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__uuid)?,
                                },
                        }))
            }
        }
        impl bevy_reflect::FromReflect for UntypedHandle where  {
            fn from_reflect(__param0: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Enum(__param0) =
                        bevy_reflect::PartialReflect::reflect_ref(__param0) {
                    match bevy_reflect::enums::Enum::variant_name(__param0) {
                        "Strong" =>
                            ::core::option::Option::Some(UntypedHandle::Strong {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <Arc<StrongHandle> as
                                                    bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        "Uuid" =>
                            ::core::option::Option::Some(UntypedHandle::Uuid {
                                    type_id: {
                                        let __type_id = __param0.field("type_id");
                                        let __type_id = __type_id?;
                                        <TypeId as
                                                    bevy_reflect::FromReflect>::from_reflect(__type_id)?
                                    },
                                    uuid: {
                                        let __uuid = __param0.field("uuid");
                                        let __uuid = __uuid?;
                                        <Uuid as bevy_reflect::FromReflect>::from_reflect(__uuid)?
                                    },
                                }),
                        name => ::core::option::Option::None,
                    }
                } else { ::core::option::Option::None }
            }
        }
    };Reflect)]
477pub enum UntypedHandle {
478    /// A strong handle, which will keep the referenced [`Asset`] alive until all strong handles are dropped.
479    Strong(Arc<StrongHandle>),
480    /// A UUID handle, which does not keep the referenced [`Asset`] alive.
481    Uuid {
482        /// An identifier that records the underlying asset type.
483        type_id: TypeId,
484        /// The UUID provided during asset registration.
485        uuid: Uuid,
486    },
487}
488
489impl UntypedHandle {
490    /// Returns the equivalent of [`Handle`]'s default implementation for the given type ID.
491    pub fn default_for_type(type_id: TypeId) -> Self {
492        Self::Uuid {
493            type_id,
494            uuid: AssetId::<()>::DEFAULT_UUID,
495        }
496    }
497
498    /// Returns the [`UntypedAssetId`] for the referenced asset.
499    #[inline]
500    pub fn id(&self) -> UntypedAssetId {
501        match self {
502            UntypedHandle::Strong(handle) => UntypedAssetId::Index {
503                type_id: handle.type_id,
504                index: handle.index,
505            },
506            UntypedHandle::Uuid { type_id, uuid } => UntypedAssetId::Uuid {
507                uuid: *uuid,
508                type_id: *type_id,
509            },
510        }
511    }
512
513    /// Returns the path if this is (1) a strong handle and (2) the asset has a path
514    #[inline]
515    pub fn path(&self) -> Option<&AssetPath<'static>> {
516        match self {
517            UntypedHandle::Strong(handle) => handle.path.as_ref(),
518            UntypedHandle::Uuid { .. } => None,
519        }
520    }
521
522    /// Returns the [`TypeId`] of the referenced [`Asset`].
523    #[inline]
524    pub fn type_id(&self) -> TypeId {
525        match self {
526            UntypedHandle::Strong(handle) => handle.type_id,
527            UntypedHandle::Uuid { type_id, .. } => *type_id,
528        }
529    }
530
531    /// Converts to a typed Handle. This _will not check if the target Handle type matches_.
532    #[inline]
533    pub fn typed_unchecked<A: Asset>(self) -> Handle<A> {
534        match self {
535            UntypedHandle::Strong(handle) => Handle::Strong(handle),
536            UntypedHandle::Uuid { uuid, .. } => Handle::Uuid(uuid, PhantomData),
537        }
538    }
539
540    /// Converts to a typed Handle. This will check the type when compiled with debug asserts, but it
541    ///  _will not check if the target Handle type matches in release builds_. Use this as an optimization
542    /// when you want some degree of validation at dev-time, but you are also very certain that the type
543    /// actually matches.
544    #[inline]
545    pub fn typed_debug_checked<A: Asset>(self) -> Handle<A> {
546        if true {
    {
        match (&self.type_id(), &TypeId::of::<A>()) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val,
                        ::core::option::Option::Some(format_args!("The target Handle<A>\'s TypeId does not match the TypeId of this UntypedHandle")));
                }
            }
        }
    };
};debug_assert_eq!(
547            self.type_id(),
548            TypeId::of::<A>(),
549            "The target Handle<A>'s TypeId does not match the TypeId of this UntypedHandle"
550        );
551        self.typed_unchecked()
552    }
553
554    /// Converts to a typed Handle. This will panic if the internal [`TypeId`] does not match the given asset type `A`
555    #[inline]
556    pub fn typed<A: Asset>(self) -> Handle<A> {
557        let Ok(handle) = self.try_typed() else {
558            {
    ::core::panicking::panic_fmt(format_args!("The target Handle<{0}>\'s TypeId does not match the TypeId of this UntypedHandle",
            core::any::type_name::<A>()));
}panic!(
559                "The target Handle<{}>'s TypeId does not match the TypeId of this UntypedHandle",
560                core::any::type_name::<A>()
561            )
562        };
563
564        handle
565    }
566
567    /// Converts to a typed Handle. This will panic if the internal [`TypeId`] does not match the given asset type `A`
568    #[inline]
569    pub fn try_typed<A: Asset>(self) -> Result<Handle<A>, UntypedAssetConversionError> {
570        Handle::try_from(self)
571    }
572
573    /// The "meta transform" for the strong handle. This will only be [`Some`] if the handle is strong and there is a meta transform
574    /// associated with it.
575    #[inline]
576    pub fn meta_transform(&self) -> Option<&MetaTransform> {
577        match self {
578            UntypedHandle::Strong(handle) => handle.meta_transform.as_ref(),
579            UntypedHandle::Uuid { .. } => None,
580        }
581    }
582}
583
584impl PartialEq for UntypedHandle {
585    #[inline]
586    fn eq(&self, other: &Self) -> bool {
587        self.id() == other.id() && self.type_id() == other.type_id()
588    }
589}
590
591impl Eq for UntypedHandle {}
592
593impl Hash for UntypedHandle {
594    #[inline]
595    fn hash<H: Hasher>(&self, state: &mut H) {
596        self.id().hash(state);
597    }
598}
599
600impl core::fmt::Debug for UntypedHandle {
601    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
602        match self {
603            UntypedHandle::Strong(handle) => {
604                f.write_fmt(format_args!("StrongHandle{{ type_id: {0:?}, id: {1:?}, path: {2:?} }}",
        handle.type_id, handle.index, handle.path))write!(
605                    f,
606                    "StrongHandle{{ type_id: {:?}, id: {:?}, path: {:?} }}",
607                    handle.type_id, handle.index, handle.path
608                )
609            }
610            UntypedHandle::Uuid { type_id, uuid } => {
611                f.write_fmt(format_args!("UuidHandle{{ type_id: {0:?}, uuid: {1:?} }}",
        type_id, uuid))write!(f, "UuidHandle{{ type_id: {type_id:?}, uuid: {uuid:?} }}",)
612            }
613        }
614    }
615}
616
617impl PartialOrd for UntypedHandle {
618    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
619        if self.type_id() == other.type_id() {
620            self.id().partial_cmp(&other.id())
621        } else {
622            None
623        }
624    }
625}
626
627impl From<&UntypedHandle> for UntypedAssetId {
628    #[inline]
629    fn from(value: &UntypedHandle) -> Self {
630        value.id()
631    }
632}
633
634// Cross Operations
635
636impl<A: Asset> PartialEq<UntypedHandle> for Handle<A> {
637    #[inline]
638    fn eq(&self, other: &UntypedHandle) -> bool {
639        TypeId::of::<A>() == other.type_id() && self.id() == other.id()
640    }
641}
642
643impl<A: Asset> PartialEq<Handle<A>> for UntypedHandle {
644    #[inline]
645    fn eq(&self, other: &Handle<A>) -> bool {
646        other.eq(self)
647    }
648}
649
650impl<A: Asset> PartialOrd<UntypedHandle> for Handle<A> {
651    #[inline]
652    fn partial_cmp(&self, other: &UntypedHandle) -> Option<core::cmp::Ordering> {
653        if TypeId::of::<A>() != other.type_id() {
654            None
655        } else {
656            self.id().partial_cmp(&other.id())
657        }
658    }
659}
660
661impl<A: Asset> PartialOrd<Handle<A>> for UntypedHandle {
662    #[inline]
663    fn partial_cmp(&self, other: &Handle<A>) -> Option<core::cmp::Ordering> {
664        Some(other.partial_cmp(self)?.reverse())
665    }
666}
667
668impl<A: Asset> From<Handle<A>> for UntypedHandle {
669    fn from(value: Handle<A>) -> Self {
670        match value {
671            Handle::Strong(handle) => UntypedHandle::Strong(handle),
672            Handle::Uuid(uuid, _) => UntypedHandle::Uuid {
673                type_id: TypeId::of::<A>(),
674                uuid,
675            },
676        }
677    }
678}
679
680impl<A: Asset> TryFrom<UntypedHandle> for Handle<A> {
681    type Error = UntypedAssetConversionError;
682
683    fn try_from(value: UntypedHandle) -> Result<Self, Self::Error> {
684        let found = value.type_id();
685        let expected = TypeId::of::<A>();
686
687        if found != expected {
688            return Err(UntypedAssetConversionError::TypeIdMismatch { expected, found });
689        }
690
691        Ok(match value {
692            UntypedHandle::Strong(handle) => Handle::Strong(handle),
693            UntypedHandle::Uuid { uuid, .. } => Handle::Uuid(uuid, PhantomData),
694        })
695    }
696}
697
698/// Creates a [`Handle`] from a string literal containing a UUID.
699///
700/// # Examples
701///
702/// ```
703/// # use bevy_asset::{Handle, uuid_handle};
704/// # type Image = ();
705/// const IMAGE: Handle<Image> = uuid_handle!("1347c9b7-c46a-48e7-b7b8-023a354b7cac");
706/// ```
707#[macro_export]
708macro_rules! uuid_handle {
709    ($uuid:expr) => {{
710        $crate::Handle::Uuid($crate::uuid::uuid!($uuid), core::marker::PhantomData)
711    }};
712}
713
714#[deprecated = "Use uuid_handle! instead"]
715#[macro_export]
716macro_rules! weak_handle {
717    ($uuid:expr) => {
718        $crate::uuid_handle!($uuid)
719    };
720}
721
722/// Errors preventing the conversion of to/from an [`UntypedHandle`] and a [`Handle`].
723#[derive(#[allow(unused_qualifications)]
#[automatically_derived]
impl ::core::fmt::Display for UntypedAssetConversionError {
    fn fmt(&self, __formatter: &mut ::core::fmt::Formatter)
        -> ::core::fmt::Result {

        #[allow(unused_variables, deprecated, clippy ::
        used_underscore_binding)]
        match self {
            UntypedAssetConversionError::TypeIdMismatch { expected, found } =>
                match (found, expected) {
                    (__field_found, __field_expected) =>
                        __formatter.write_fmt(format_args!("This UntypedHandle is for {0:?} and cannot be converted into a Handle<{1:?}>",
                                __field_found, __field_expected)),
                },
        }
    }
}Error, #[automatically_derived]
impl ::core::fmt::Debug for UntypedAssetConversionError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            UntypedAssetConversionError::TypeIdMismatch {
                expected: __self_0, found: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "TypeIdMismatch", "expected", __self_0, "found", &__self_1),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for UntypedAssetConversionError {
    #[inline]
    fn eq(&self, other: &UntypedAssetConversionError) -> bool {
        match (self, other) {
            (UntypedAssetConversionError::TypeIdMismatch {
                expected: __self_0, found: __self_1 },
                UntypedAssetConversionError::TypeIdMismatch {
                expected: __arg1_0, found: __arg1_1 }) =>
                __self_0 == __arg1_0 && __self_1 == __arg1_1,
        }
    }
}PartialEq, #[automatically_derived]
impl ::core::clone::Clone for UntypedAssetConversionError {
    #[inline]
    fn clone(&self) -> UntypedAssetConversionError {
        match self {
            UntypedAssetConversionError::TypeIdMismatch {
                expected: __self_0, found: __self_1 } =>
                UntypedAssetConversionError::TypeIdMismatch {
                    expected: ::core::clone::Clone::clone(__self_0),
                    found: ::core::clone::Clone::clone(__self_1),
                },
        }
    }
}Clone)]
724#[non_exhaustive]
725pub enum UntypedAssetConversionError {
726    /// Caused when trying to convert an [`UntypedHandle`] into a [`Handle`] of the wrong type.
727    #[error(
728        "This UntypedHandle is for {found:?} and cannot be converted into a Handle<{expected:?}>"
729    )]
730    TypeIdMismatch {
731        /// The expected [`TypeId`] of the [`Handle`] being converted to.
732        expected: TypeId,
733        /// The [`TypeId`] of the [`UntypedHandle`] being converted from.
734        found: TypeId,
735    },
736}
737
738#[cfg(test)]
739mod tests {
740    use alloc::boxed::Box;
741    use bevy_platform::hash::FixedHasher;
742    use bevy_reflect::PartialReflect;
743    use core::hash::BuildHasher;
744    use uuid::Uuid;
745
746    use crate::tests::create_app;
747
748    use super::*;
749
750    type TestAsset = ();
751
752    const UUID_1: Uuid = Uuid::from_u128(123);
753    const UUID_2: Uuid = Uuid::from_u128(456);
754
755    /// Simple utility to directly hash a value using a fixed hasher
756    fn hash<T: Hash>(data: &T) -> u64 {
757        FixedHasher.hash_one(data)
758    }
759
760    /// Typed and Untyped `Handles` should be equivalent to each other and themselves
761    #[test]
762    fn equality() {
763        let typed = Handle::<TestAsset>::Uuid(UUID_1, PhantomData);
764        let untyped = UntypedHandle::Uuid {
765            type_id: TypeId::of::<TestAsset>(),
766            uuid: UUID_1,
767        };
768
769        assert_eq!(
770            Ok(typed.clone()),
771            Handle::<TestAsset>::try_from(untyped.clone())
772        );
773        assert_eq!(UntypedHandle::from(typed.clone()), untyped);
774        assert_eq!(typed, untyped);
775    }
776
777    /// Typed and Untyped `Handles` should be orderable amongst each other and themselves
778    #[test]
779    #[expect(
780        clippy::cmp_owned,
781        reason = "This lints on the assertion that a typed handle converted to an untyped handle maintains its ordering compared to an untyped handle. While the conversion would normally be useless, we need to ensure that converted handles maintain their ordering, making the conversion necessary here."
782    )]
783    fn ordering() {
784        assert!(UUID_1 < UUID_2);
785
786        let typed_1 = Handle::<TestAsset>::Uuid(UUID_1, PhantomData);
787        let typed_2 = Handle::<TestAsset>::Uuid(UUID_2, PhantomData);
788        let untyped_1 = UntypedHandle::Uuid {
789            type_id: TypeId::of::<TestAsset>(),
790            uuid: UUID_1,
791        };
792        let untyped_2 = UntypedHandle::Uuid {
793            type_id: TypeId::of::<TestAsset>(),
794            uuid: UUID_2,
795        };
796
797        assert!(typed_1 < typed_2);
798        assert!(untyped_1 < untyped_2);
799
800        assert!(UntypedHandle::from(typed_1.clone()) < untyped_2);
801        assert!(untyped_1 < UntypedHandle::from(typed_2.clone()));
802
803        assert!(Handle::<TestAsset>::try_from(untyped_1.clone()).unwrap() < typed_2);
804        assert!(typed_1 < Handle::<TestAsset>::try_from(untyped_2.clone()).unwrap());
805
806        assert!(typed_1 < untyped_2);
807        assert!(untyped_1 < typed_2);
808    }
809
810    /// Typed and Untyped `Handles` should be equivalently hashable to each other and themselves
811    #[test]
812    fn hashing() {
813        let typed = Handle::<TestAsset>::Uuid(UUID_1, PhantomData);
814        let untyped = UntypedHandle::Uuid {
815            type_id: TypeId::of::<TestAsset>(),
816            uuid: UUID_1,
817        };
818
819        assert_eq!(
820            hash(&typed),
821            hash(&Handle::<TestAsset>::try_from(untyped.clone()).unwrap())
822        );
823        assert_eq!(hash(&UntypedHandle::from(typed.clone())), hash(&untyped));
824        assert_eq!(hash(&typed), hash(&untyped));
825    }
826
827    /// Typed and Untyped `Handles` should be interchangeable
828    #[test]
829    fn conversion() {
830        let typed = Handle::<TestAsset>::Uuid(UUID_1, PhantomData);
831        let untyped = UntypedHandle::Uuid {
832            type_id: TypeId::of::<TestAsset>(),
833            uuid: UUID_1,
834        };
835
836        assert_eq!(typed, Handle::try_from(untyped.clone()).unwrap());
837        assert_eq!(UntypedHandle::from(typed.clone()), untyped);
838    }
839
840    #[test]
841    fn from_uuid() {
842        let uuid = UUID_1;
843        let handle: Handle<TestAsset> = uuid.into();
844
845        assert!(handle.is_uuid());
846        assert_eq!(handle.id(), AssetId::Uuid { uuid });
847    }
848
849    /// `PartialReflect::reflect_clone`/`PartialReflect::to_dynamic` should increase the strong count of a strong handle
850    #[test]
851    fn strong_handle_reflect_clone() {
852        use crate::{AssetApp, Assets, VisitAssetDependencies};
853        use bevy_reflect::FromReflect;
854
855        #[derive(Reflect)]
856        struct MyAsset {
857            value: u32,
858        }
859        impl Asset for MyAsset {}
860        impl VisitAssetDependencies for MyAsset {
861            fn visit_dependencies(&self, _visit: &mut impl FnMut(UntypedAssetId)) {}
862        }
863
864        let mut app = create_app().0;
865        app.init_asset::<MyAsset>();
866        let mut assets = app.world_mut().resource_mut::<Assets<MyAsset>>();
867
868        let handle: Handle<MyAsset> = assets.add(MyAsset { value: 1 });
869        match &handle {
870            Handle::Strong(strong) => {
871                assert_eq!(
872                    Arc::strong_count(strong),
873                    1,
874                    "Inserting the asset should result in a strong count of 1"
875                );
876
877                let reflected: &dyn Reflect = &handle;
878                let _cloned_handle: Box<dyn Reflect> = reflected.reflect_clone().unwrap();
879
880                assert_eq!(
881                    Arc::strong_count(strong),
882                    2,
883                    "Cloning the handle with reflect should increase the strong count to 2"
884                );
885
886                let dynamic_handle: Box<dyn PartialReflect> = reflected.to_dynamic();
887
888                assert_eq!(
889                    Arc::strong_count(strong),
890                    3,
891                    "Converting the handle to a dynamic should increase the strong count to 3"
892                );
893
894                let from_reflect_handle: Handle<MyAsset> =
895                    FromReflect::from_reflect(&*dynamic_handle).unwrap();
896
897                assert_eq!(Arc::strong_count(strong), 4, "Converting the reflected value back to a handle should increase the strong count to 4");
898                assert!(
899                    from_reflect_handle.is_strong(),
900                    "The cloned handle should still be strong"
901                );
902            }
903            _ => panic!("Expected a strong handle"),
904        }
905    }
906
907    #[test]
908    fn handle_from_reflect_verifies_type_id() {
909        use crate::{AssetApp, Assets};
910        use bevy_reflect::FromReflect;
911
912        #[derive(Reflect, Asset)]
913        struct A;
914        #[derive(Reflect, Asset)]
915        struct B;
916
917        let mut app = create_app().0;
918        app.init_asset::<A>().init_asset::<B>();
919
920        let mut assets = app.world_mut().resource_mut::<Assets<A>>();
921        let handle_a = assets.add(A);
922
923        let dynamic_handle_a = handle_a.to_dynamic();
924        let reflected_handle_a = handle_a.as_partial_reflect();
925
926        let handle_b_from_reflect_dynamic: Option<Handle<B>> =
927            FromReflect::from_reflect(&*dynamic_handle_a);
928        let handle_b_from_reflect: Option<Handle<B>> =
929            FromReflect::from_reflect(reflected_handle_a);
930        let handle_a_from_reflect: Option<Handle<A>> =
931            FromReflect::from_reflect(reflected_handle_a);
932        assert!(
933            handle_b_from_reflect.is_none(),
934            "Handle<B> should not be constructible from reflected Handle<A>"
935        );
936        assert!(
937            handle_b_from_reflect_dynamic.is_none(),
938            "Handle<B> should not be constructible from dynamic Handle<A>"
939        );
940        assert!(
941            handle_a_from_reflect.is_some(),
942            "Handle<A> should be constructible from reflected Handle<A>"
943        );
944    }
945}