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> {
|
impl AssetSourceId<'static> {
|
||||||
fn from(value: &'static str) -> Self {
|
/// Indicates this [`AssetSourceId`] should have a static lifetime.
|
||||||
AssetSourceId::Name(value.into())
|
#[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> {
|
impl<'a> From<Option<&'a str>> for AssetSourceId<'a> {
|
||||||
fn from(value: Option<&'static str>) -> Self {
|
fn from(value: Option<&'a str>) -> Self {
|
||||||
match value {
|
match value {
|
||||||
Some(value) => AssetSourceId::Name(value.into()),
|
Some(value) => AssetSourceId::Name(CowArc::Borrowed(value)),
|
||||||
None => AssetSourceId::Default,
|
None => AssetSourceId::Default,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,7 +319,7 @@ pub struct AssetSourceBuilders {
|
||||||
impl AssetSourceBuilders {
|
impl AssetSourceBuilders {
|
||||||
/// Inserts a new builder with the given `id`
|
/// Inserts a new builder with the given `id`
|
||||||
pub fn insert(&mut self, id: impl Into<AssetSourceId<'static>>, source: AssetSourceBuilder) {
|
pub fn insert(&mut self, id: impl Into<AssetSourceId<'static>>, source: AssetSourceBuilder) {
|
||||||
match id.into() {
|
match AssetSourceId::from_static(id) {
|
||||||
AssetSourceId::Default => {
|
AssetSourceId::Default => {
|
||||||
self.default = Some(source);
|
self.default = Some(source);
|
||||||
}
|
}
|
||||||
|
|
|
@ -341,7 +341,7 @@ impl AssetApp for App {
|
||||||
id: impl Into<AssetSourceId<'static>>,
|
id: impl Into<AssetSourceId<'static>>,
|
||||||
source: AssetSourceBuilder,
|
source: AssetSourceBuilder,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
let id = id.into();
|
let id = AssetSourceId::from_static(id);
|
||||||
if self.world().get_resource::<AssetServer>().is_some() {
|
if self.world().get_resource::<AssetServer>().is_some() {
|
||||||
error!("{} must be registered before `AssetPlugin` (typically added as part of `DefaultPlugins`)", id);
|
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]
|
#[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();
|
let (source, path, label) = Self::parse_internal(asset_path).unwrap();
|
||||||
|
|
||||||
AssetPath {
|
AssetPath {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
path: CowArc::Static(path),
|
path: CowArc::Borrowed(path),
|
||||||
label: label.map(CowArc::Static),
|
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]
|
#[inline]
|
||||||
fn from(path: &'static Path) -> Self {
|
fn from(path: &'a Path) -> Self {
|
||||||
Self {
|
Self {
|
||||||
source: AssetSourceId::Default,
|
source: AssetSourceId::Default,
|
||||||
path: CowArc::Static(path),
|
path: CowArc::Borrowed(path),
|
||||||
label: None,
|
label: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,18 @@ pub enum CowArc<'a, T: ?Sized + 'static> {
|
||||||
Owned(Arc<T>),
|
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> {
|
impl<'a, T: ?Sized> Deref for CowArc<'a, T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue