khora_core/asset/handle.rs
1// Copyright 2025 eraflo
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use super::Asset;
16use std::{ops::Deref, sync::Arc};
17
18/// A thread-safe, reference-counted handle to a loaded asset's data.
19///
20/// This struct acts as a smart pointer that provides shared ownership of asset
21/// data in memory. It is the primary way that game logic and systems should
22/// interact with loaded assets.
23///
24/// Cloning an `AssetHandle` is a very cheap operation, as it only increments an
25/// atomic reference counter. It does not duplicate the underlying asset data. The
26/// asset data is automatically deallocated when the last handle pointing to it
27/// is dropped.
28///
29/// This handle dereferences to `&T`, allowing for transparent, read-only access
30/// to the asset's contents.
31///
32/// # Examples
33///
34/// ```
35/// # use khora_core::asset::{Asset, AssetHandle};
36/// # struct Texture {}
37/// # impl Asset for Texture {}
38/// let texture = Texture {};
39///
40/// // The AssetAgent creates the first handle when loading is complete.
41/// let handle1 = AssetHandle::new(texture);
42///
43/// // Other systems can clone the handle to share access.
44/// let handle2 = handle1.clone();
45///
46/// // Accessing the data is done via dereferencing (like with `Arc` or `Box`).
47/// // let width = handle1.width; // Assuming Texture has a `width` field.
48/// ```
49#[derive(Debug)]
50pub struct AssetHandle<T: Asset>(Arc<T>);
51
52impl<T: Asset> AssetHandle<T> {
53 /// Creates a new `AssetHandle` that takes ownership of the asset data.
54 ///
55 /// This is typically called by an asset loading system (like an `AssetAgent`)
56 /// once an asset has been successfully loaded into memory.
57 pub fn new(asset: T) -> Self {
58 Self(Arc::new(asset))
59 }
60}
61
62impl<T: Asset> Clone for AssetHandle<T> {
63 /// Clones the handle, incrementing the reference count to the underlying asset.
64 fn clone(&self) -> Self {
65 Self(self.0.clone())
66 }
67}
68
69impl<T: Asset> Deref for AssetHandle<T> {
70 type Target = T;
71
72 /// Provides transparent, immutable access to the underlying asset data.
73 fn deref(&self) -> &Self::Target {
74 &self.0
75 }
76}