mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Generalized Into<AssetSourceId>
and Into<AssetPath>
Implementations over Lifetime (#10823)
# Objective - Fixes #10478 ## Solution Generalised `From/Into` implementations over `&str` and `Option<&str>` for `AssetSourceId` and `AssetPath` across all lifetimes, not just static. To maintain access to the `'static`-only specialisation, these types (and `CowArc`) now include an `as_static` method which will apply the specialisation. ```rust // Snipped from `AssetApp` fn register_asset_source( &mut self, id: impl Into<AssetSourceId<'static>>, // ^^^^^^^ // | as_static is only available for 'static lifetimes source: AssetSourceBuilder, ) -> &mut Self { let id = id.into().as_static(); // ^^^^^^ ^^^^^^^^^ // | | Specialized (internally storing CowArc::Static) // | Generic Into (internally storing CowArc::Borrowed) // ... } ``` This post-fix specialisation is available here because the actual specialisation performed is only a marker for if/when modification or ownership is required, making the transform a very cheap operation. For cleanliness, I've also added `from_static`, which wraps this behaviour in a clean shorthand designed to replace `from` calls. --- ## Changelog - Generalised the following implementations over a generic lifetime: - `From<&'static str> for AssetSourceId<'static>` - `From<Option<&'static str>> for AssetSourceId<'static>` - `From<&'static str> for AssetPath<'static>` - `From<&'static Path> for AssetPath<'static>` - Added `as_static` specialisation to: - `CowArc` - `AssetSourceId` - `AssetPath` - Added `from_static` specialised constructor to: - `AssetSourceId` - `AssetPath` ## Migration Guide In areas where these implementations where being used, you can now add `from_static` in order to get the original specialised implementation which avoids creating an `Arc` internally. ```rust // Before let asset_path = AssetPath::from("my/path/to/an/asset.ext"); // After let asset_path = AssetPath::from_static("my/path/to/an/asset.ext"); ``` To be clear, this is only required if you wish to maintain the performance benefit that came with the specialisation. Existing code is _not_ broken by this change.
This commit is contained in:
parent
035fb78d6c
commit
491aec8e5b
4 changed files with 73 additions and 15 deletions
|
@ -70,9 +70,26 @@ impl<'a> AssetSourceId<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&'static str> for AssetSourceId<'static> {
|
||||
fn from(value: &'static str) -> Self {
|
||||
AssetSourceId::Name(value.into())
|
||||
impl AssetSourceId<'static> {
|
||||
/// Indicates this [`AssetSourceId`] should have a static lifetime.
|
||||
#[inline]
|
||||
pub fn as_static(self) -> Self {
|
||||
match self {
|
||||
Self::Default => Self::Default,
|
||||
Self::Name(value) => Self::Name(value.as_static()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs an [`AssetSourceId`] with a static lifetime.
|
||||
#[inline]
|
||||
pub fn from_static(value: impl Into<Self>) -> Self {
|
||||
value.into().as_static()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for AssetSourceId<'a> {
|
||||
fn from(value: &'a str) -> Self {
|
||||
AssetSourceId::Name(CowArc::Borrowed(value))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,10 +99,10 @@ impl<'a, 'b> From<&'a AssetSourceId<'b>> for AssetSourceId<'b> {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Option<&'static str>> for AssetSourceId<'static> {
|
||||
fn from(value: Option<&'static str>) -> Self {
|
||||
impl<'a> From<Option<&'a str>> for AssetSourceId<'a> {
|
||||
fn from(value: Option<&'a str>) -> Self {
|
||||
match value {
|
||||
Some(value) => AssetSourceId::Name(value.into()),
|
||||
Some(value) => AssetSourceId::Name(CowArc::Borrowed(value)),
|
||||
None => AssetSourceId::Default,
|
||||
}
|
||||
}
|
||||
|
@ -302,7 +319,7 @@ pub struct AssetSourceBuilders {
|
|||
impl AssetSourceBuilders {
|
||||
/// Inserts a new builder with the given `id`
|
||||
pub fn insert(&mut self, id: impl Into<AssetSourceId<'static>>, source: AssetSourceBuilder) {
|
||||
match id.into() {
|
||||
match AssetSourceId::from_static(id) {
|
||||
AssetSourceId::Default => {
|
||||
self.default = Some(source);
|
||||
}
|
||||
|
|
|
@ -341,7 +341,7 @@ impl AssetApp for App {
|
|||
id: impl Into<AssetSourceId<'static>>,
|
||||
source: AssetSourceBuilder,
|
||||
) -> &mut Self {
|
||||
let id = id.into();
|
||||
let id = AssetSourceId::from_static(id);
|
||||
if self.world().get_resource::<AssetServer>().is_some() {
|
||||
error!("{} must be registered before `AssetPlugin` (typically added as part of `DefaultPlugins`)", id);
|
||||
}
|
||||
|
|
|
@ -475,14 +475,43 @@ impl<'a> AssetPath<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&'static str> for AssetPath<'static> {
|
||||
impl AssetPath<'static> {
|
||||
/// Indicates this [`AssetPath`] should have a static lifetime.
|
||||
#[inline]
|
||||
fn from(asset_path: &'static str) -> Self {
|
||||
pub fn as_static(self) -> Self {
|
||||
let Self {
|
||||
source,
|
||||
path,
|
||||
label,
|
||||
} = self;
|
||||
|
||||
let source = source.as_static();
|
||||
let path = path.as_static();
|
||||
let label = label.map(CowArc::as_static);
|
||||
|
||||
Self {
|
||||
source,
|
||||
path,
|
||||
label,
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs an [`AssetPath`] with a static lifetime.
|
||||
#[inline]
|
||||
pub fn from_static(value: impl Into<Self>) -> Self {
|
||||
value.into().as_static()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for AssetPath<'a> {
|
||||
#[inline]
|
||||
fn from(asset_path: &'a str) -> Self {
|
||||
let (source, path, label) = Self::parse_internal(asset_path).unwrap();
|
||||
|
||||
AssetPath {
|
||||
source: source.into(),
|
||||
path: CowArc::Static(path),
|
||||
label: label.map(CowArc::Static),
|
||||
path: CowArc::Borrowed(path),
|
||||
label: label.map(CowArc::Borrowed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -501,12 +530,12 @@ impl From<String> for AssetPath<'static> {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&'static Path> for AssetPath<'static> {
|
||||
impl<'a> From<&'a Path> for AssetPath<'a> {
|
||||
#[inline]
|
||||
fn from(path: &'static Path) -> Self {
|
||||
fn from(path: &'a Path) -> Self {
|
||||
Self {
|
||||
source: AssetSourceId::Default,
|
||||
path: CowArc::Static(path),
|
||||
path: CowArc::Borrowed(path),
|
||||
label: None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,18 @@ pub enum CowArc<'a, T: ?Sized + 'static> {
|
|||
Owned(Arc<T>),
|
||||
}
|
||||
|
||||
impl<T: ?Sized> CowArc<'static, T> {
|
||||
/// Indicates this [`CowArc`] should have a static lifetime.
|
||||
/// This ensures if this was created with a value `Borrowed(&'static T)`, it is replaced with `Static(&'static T)`.
|
||||
#[inline]
|
||||
pub fn as_static(self) -> Self {
|
||||
match self {
|
||||
Self::Borrowed(value) | Self::Static(value) => Self::Static(value),
|
||||
Self::Owned(value) => Self::Owned(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> Deref for CowArc<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
|
|
Loading…
Reference in a new issue