1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
use std::borrow::Borrow;
use bevy::asset::AssetPath;
/// A type that can be used as key for mapped asset collection.
///
/// # `String` and `Box<str>`
///
/// Both [`String`] and [`Box<str>`] implements [`MapKey`] by using
/// the path of the asset as the key.
///
/// # Key collision
///
/// Following the implementation of the [`MapKey`] trait, key collisions may happen,
/// resulting in some assets not being loaded.
/// This is up to the user to ensure that there are no collisions.
pub trait MapKey {
/// Creates the key from the path of the asset.
fn from_asset_path(path: &AssetPath) -> Self;
}
/// Implements extra traits and methods for the key types.
macro_rules! impl_map_key_extras {
($Key:ty) => {
impl AsRef<str> for $Key {
#[inline]
fn as_ref(&self) -> &str {
&self.0
}
}
// Note: required by `HashMap::get` to being able to use &str.
impl Borrow<str> for $Key {
#[inline]
fn borrow(&self) -> &str {
&self.0
}
}
impl From<$Key> for Box<str> {
#[inline]
fn from(key: $Key) -> Self {
key.0
}
}
impl From<$Key> for String {
#[inline]
fn from(key: $Key) -> Self {
key.0.into()
}
}
};
}
/// A [`MapKey`] that uses the [`file_name`] of the asset's path as key.
///
/// # Key collision
///
/// Since [`FileName`] uses a subset of the asset path, two different assets may have the same key.
/// It’s up to you to ensure there is no collision.
///
/// Here's an example that will result in a key clash.
///
/// ```plain
/// folder
/// subfolder_a
/// file.png
/// subfolder_b
/// file.png
/// ```
///
/// [`file_name`]: std::path::Path::file_name
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FileName(Box<str>);
impl_map_key_extras!(FileName);
impl MapKey for FileName {
#[inline]
fn from_asset_path(path: &AssetPath) -> Self {
Self(
path.path()
.file_name()
.unwrap()
.to_str()
.expect("Path should be valid UTF-8")
.into(),
)
}
}
/// A [`MapKey`] that uses the [`file_stem`] of the asset's path as key.
///
/// # Key collision
///
/// Since [`FileStem`] uses a subset of the asset path, two different assets may have the same key.
/// It’s up to you to ensure there is no collision.
///
/// Here's an example that will result in a key clash.
///
/// ```plain
/// folder
/// file.png
/// file.jpg
/// ```
///
/// [`file_stem`]: std::path::Path::file_stem
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FileStem(Box<str>);
impl_map_key_extras!(FileStem);
impl MapKey for FileStem {
#[inline]
fn from_asset_path(path: &AssetPath) -> Self {
Self(
path.path()
.file_stem()
.unwrap()
.to_str()
.expect("Path should be valid UTF-8")
.into(),
)
}
}
impl MapKey for String {
#[inline]
fn from_asset_path(path: &AssetPath) -> Self {
path_slash::PathExt::to_slash(path.path())
.expect("Path should be valid UTF-8")
.into()
}
}
impl MapKey for Box<str> {
#[inline]
fn from_asset_path(path: &AssetPath) -> Self {
path_slash::PathExt::to_slash(path.path())
.expect("Path should be valid UTF-8")
.into()
}
}