 d70595b667
			
		
	
	
		d70595b667
		
			
		
	
	
	
	
		
			
			# Objective - Fixes #6370 - Closes #6581 ## Solution - Added the following lints to the workspace: - `std_instead_of_core` - `std_instead_of_alloc` - `alloc_instead_of_core` - Used `cargo +nightly fmt` with [item level use formatting](https://rust-lang.github.io/rustfmt/?version=v1.6.0&search=#Item%5C%3A) to split all `use` statements into single items. - Used `cargo clippy --workspace --all-targets --all-features --fix --allow-dirty` to _attempt_ to resolve the new linting issues, and intervened where the lint was unable to resolve the issue automatically (usually due to needing an `extern crate alloc;` statement in a crate root). - Manually removed certain uses of `std` where negative feature gating prevented `--all-features` from finding the offending uses. - Used `cargo +nightly fmt` with [crate level use formatting](https://rust-lang.github.io/rustfmt/?version=v1.6.0&search=#Crate%5C%3A) to re-merge all `use` statements matching Bevy's previous styling. - Manually fixed cases where the `fmt` tool could not re-merge `use` statements due to conditional compilation attributes. ## Testing - Ran CI locally ## Migration Guide The MSRV is now 1.81. Please update to this version or higher. ## Notes - This is a _massive_ change to try and push through, which is why I've outlined the semi-automatic steps I used to create this PR, in case this fails and someone else tries again in the future. - Making this change has no impact on user code, but does mean Bevy contributors will be warned to use `core` and `alloc` instead of `std` where possible. - This lint is a critical first step towards investigating `no_std` options for Bevy. --------- Co-authored-by: François Mockers <francois.mockers@vleue.com>
		
			
				
	
	
		
			282 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			282 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use crate::{meta::Settings, Asset, ErasedLoadedAsset, Handle, LabeledAsset, UntypedHandle};
 | |
| use atomicow::CowArc;
 | |
| use bevy_utils::{ConditionalSendFuture, HashMap};
 | |
| use core::{
 | |
|     borrow::Borrow,
 | |
|     convert::Infallible,
 | |
|     hash::Hash,
 | |
|     marker::PhantomData,
 | |
|     ops::{Deref, DerefMut},
 | |
| };
 | |
| use serde::{Deserialize, Serialize};
 | |
| 
 | |
| /// Transforms an [`Asset`] of a given [`AssetTransformer::AssetInput`] type to an [`Asset`] of [`AssetTransformer::AssetOutput`] type.
 | |
| ///
 | |
| /// This trait is commonly used in association with [`LoadTransformAndSave`](crate::processor::LoadTransformAndSave) to accomplish common asset pipeline workflows.
 | |
| pub trait AssetTransformer: Send + Sync + 'static {
 | |
|     /// The [`Asset`] type which this [`AssetTransformer`] takes as and input.
 | |
|     type AssetInput: Asset;
 | |
|     /// The [`Asset`] type which this [`AssetTransformer`] outputs.
 | |
|     type AssetOutput: Asset;
 | |
|     /// The settings type used by this [`AssetTransformer`].
 | |
|     type Settings: Settings + Default + Serialize + for<'a> Deserialize<'a>;
 | |
|     /// The type of [error](`std::error::Error`) which could be encountered by this transformer.
 | |
|     type Error: Into<Box<dyn core::error::Error + Send + Sync + 'static>>;
 | |
| 
 | |
|     /// Transforms the given [`TransformedAsset`] to [`AssetTransformer::AssetOutput`].
 | |
|     /// The [`TransformedAsset`]'s `labeled_assets` can be altered to add new Labeled Sub-Assets
 | |
|     /// The passed in `settings` can influence how the `asset` is transformed
 | |
|     fn transform<'a>(
 | |
|         &'a self,
 | |
|         asset: TransformedAsset<Self::AssetInput>,
 | |
|         settings: &'a Self::Settings,
 | |
|     ) -> impl ConditionalSendFuture<Output = Result<TransformedAsset<Self::AssetOutput>, Self::Error>>;
 | |
| }
 | |
| 
 | |
| /// An [`Asset`] (and any "sub assets") intended to be transformed
 | |
| pub struct TransformedAsset<A: Asset> {
 | |
|     pub(crate) value: A,
 | |
|     pub(crate) labeled_assets: HashMap<CowArc<'static, str>, LabeledAsset>,
 | |
| }
 | |
| 
 | |
| impl<A: Asset> Deref for TransformedAsset<A> {
 | |
|     type Target = A;
 | |
|     fn deref(&self) -> &Self::Target {
 | |
|         &self.value
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl<A: Asset> DerefMut for TransformedAsset<A> {
 | |
|     fn deref_mut(&mut self) -> &mut Self::Target {
 | |
|         &mut self.value
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl<A: Asset> TransformedAsset<A> {
 | |
|     /// Creates a new [`TransformedAsset`] from `asset` if its internal value matches `A`.
 | |
|     pub fn from_loaded(asset: ErasedLoadedAsset) -> Option<Self> {
 | |
|         if let Ok(value) = asset.value.downcast::<A>() {
 | |
|             return Some(TransformedAsset {
 | |
|                 value: *value,
 | |
|                 labeled_assets: asset.labeled_assets,
 | |
|             });
 | |
|         }
 | |
|         None
 | |
|     }
 | |
|     /// Creates a new [`TransformedAsset`] from `asset`, transferring the `labeled_assets` from this [`TransformedAsset`] to the new one
 | |
|     pub fn replace_asset<B: Asset>(self, asset: B) -> TransformedAsset<B> {
 | |
|         TransformedAsset {
 | |
|             value: asset,
 | |
|             labeled_assets: self.labeled_assets,
 | |
|         }
 | |
|     }
 | |
|     /// Takes the labeled assets from `labeled_source` and places them in this [`TransformedAsset`]
 | |
|     pub fn take_labeled_assets<B: Asset>(&mut self, labeled_source: TransformedAsset<B>) {
 | |
|         self.labeled_assets = labeled_source.labeled_assets;
 | |
|     }
 | |
|     /// Retrieves the value of this asset.
 | |
|     #[inline]
 | |
|     pub fn get(&self) -> &A {
 | |
|         &self.value
 | |
|     }
 | |
|     /// Mutably retrieves the value of this asset.
 | |
|     #[inline]
 | |
|     pub fn get_mut(&mut self) -> &mut A {
 | |
|         &mut self.value
 | |
|     }
 | |
|     /// Returns the labeled asset, if it exists and matches this type.
 | |
|     pub fn get_labeled<B: Asset, Q>(&mut self, label: &Q) -> Option<TransformedSubAsset<B>>
 | |
|     where
 | |
|         CowArc<'static, str>: Borrow<Q>,
 | |
|         Q: ?Sized + Hash + Eq,
 | |
|     {
 | |
|         let labeled = self.labeled_assets.get_mut(label)?;
 | |
|         let value = labeled.asset.value.downcast_mut::<B>()?;
 | |
|         Some(TransformedSubAsset {
 | |
|             value,
 | |
|             labeled_assets: &mut labeled.asset.labeled_assets,
 | |
|         })
 | |
|     }
 | |
|     /// Returns the type-erased labeled asset, if it exists and matches this type.
 | |
|     pub fn get_erased_labeled<Q>(&self, label: &Q) -> Option<&ErasedLoadedAsset>
 | |
|     where
 | |
|         CowArc<'static, str>: Borrow<Q>,
 | |
|         Q: ?Sized + Hash + Eq,
 | |
|     {
 | |
|         let labeled = self.labeled_assets.get(label)?;
 | |
|         Some(&labeled.asset)
 | |
|     }
 | |
|     /// Returns the [`UntypedHandle`] of the labeled asset with the provided 'label', if it exists.
 | |
|     pub fn get_untyped_handle<Q>(&self, label: &Q) -> Option<UntypedHandle>
 | |
|     where
 | |
|         CowArc<'static, str>: Borrow<Q>,
 | |
|         Q: ?Sized + Hash + Eq,
 | |
|     {
 | |
|         let labeled = self.labeled_assets.get(label)?;
 | |
|         Some(labeled.handle.clone())
 | |
|     }
 | |
|     /// Returns the [`Handle`] of the labeled asset with the provided 'label', if it exists and is an asset of type `B`
 | |
|     pub fn get_handle<Q, B: Asset>(&self, label: &Q) -> Option<Handle<B>>
 | |
|     where
 | |
|         CowArc<'static, str>: Borrow<Q>,
 | |
|         Q: ?Sized + Hash + Eq,
 | |
|     {
 | |
|         let labeled = self.labeled_assets.get(label)?;
 | |
|         if let Ok(handle) = labeled.handle.clone().try_typed::<B>() {
 | |
|             return Some(handle);
 | |
|         }
 | |
|         None
 | |
|     }
 | |
|     /// Adds `asset` as a labeled sub asset using `label` and `handle`
 | |
|     pub fn insert_labeled(
 | |
|         &mut self,
 | |
|         label: impl Into<CowArc<'static, str>>,
 | |
|         handle: impl Into<UntypedHandle>,
 | |
|         asset: impl Into<ErasedLoadedAsset>,
 | |
|     ) {
 | |
|         let labeled = LabeledAsset {
 | |
|             asset: asset.into(),
 | |
|             handle: handle.into(),
 | |
|         };
 | |
|         self.labeled_assets.insert(label.into(), labeled);
 | |
|     }
 | |
|     /// Iterate over all labels for "labeled assets" in the loaded asset
 | |
|     pub fn iter_labels(&self) -> impl Iterator<Item = &str> {
 | |
|         self.labeled_assets.keys().map(|s| &**s)
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// A labeled sub-asset of [`TransformedAsset`]
 | |
| pub struct TransformedSubAsset<'a, A: Asset> {
 | |
|     value: &'a mut A,
 | |
|     labeled_assets: &'a mut HashMap<CowArc<'static, str>, LabeledAsset>,
 | |
| }
 | |
| 
 | |
| impl<'a, A: Asset> Deref for TransformedSubAsset<'a, A> {
 | |
|     type Target = A;
 | |
|     fn deref(&self) -> &Self::Target {
 | |
|         self.value
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl<'a, A: Asset> DerefMut for TransformedSubAsset<'a, A> {
 | |
|     fn deref_mut(&mut self) -> &mut Self::Target {
 | |
|         self.value
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl<'a, A: Asset> TransformedSubAsset<'a, A> {
 | |
|     /// Creates a new [`TransformedSubAsset`] from `asset` if its internal value matches `A`.
 | |
|     pub fn from_loaded(asset: &'a mut ErasedLoadedAsset) -> Option<Self> {
 | |
|         let value = asset.value.downcast_mut::<A>()?;
 | |
|         Some(TransformedSubAsset {
 | |
|             value,
 | |
|             labeled_assets: &mut asset.labeled_assets,
 | |
|         })
 | |
|     }
 | |
|     /// Retrieves the value of this asset.
 | |
|     #[inline]
 | |
|     pub fn get(&self) -> &A {
 | |
|         self.value
 | |
|     }
 | |
|     /// Mutably retrieves the value of this asset.
 | |
|     #[inline]
 | |
|     pub fn get_mut(&mut self) -> &mut A {
 | |
|         self.value
 | |
|     }
 | |
|     /// Returns the labeled asset, if it exists and matches this type.
 | |
|     pub fn get_labeled<B: Asset, Q>(&mut self, label: &Q) -> Option<TransformedSubAsset<B>>
 | |
|     where
 | |
|         CowArc<'static, str>: Borrow<Q>,
 | |
|         Q: ?Sized + Hash + Eq,
 | |
|     {
 | |
|         let labeled = self.labeled_assets.get_mut(label)?;
 | |
|         let value = labeled.asset.value.downcast_mut::<B>()?;
 | |
|         Some(TransformedSubAsset {
 | |
|             value,
 | |
|             labeled_assets: &mut labeled.asset.labeled_assets,
 | |
|         })
 | |
|     }
 | |
|     /// Returns the type-erased labeled asset, if it exists and matches this type.
 | |
|     pub fn get_erased_labeled<Q>(&self, label: &Q) -> Option<&ErasedLoadedAsset>
 | |
|     where
 | |
|         CowArc<'static, str>: Borrow<Q>,
 | |
|         Q: ?Sized + Hash + Eq,
 | |
|     {
 | |
|         let labeled = self.labeled_assets.get(label)?;
 | |
|         Some(&labeled.asset)
 | |
|     }
 | |
|     /// Returns the [`UntypedHandle`] of the labeled asset with the provided 'label', if it exists.
 | |
|     pub fn get_untyped_handle<Q>(&self, label: &Q) -> Option<UntypedHandle>
 | |
|     where
 | |
|         CowArc<'static, str>: Borrow<Q>,
 | |
|         Q: ?Sized + Hash + Eq,
 | |
|     {
 | |
|         let labeled = self.labeled_assets.get(label)?;
 | |
|         Some(labeled.handle.clone())
 | |
|     }
 | |
|     /// Returns the [`Handle`] of the labeled asset with the provided 'label', if it exists and is an asset of type `B`
 | |
|     pub fn get_handle<Q, B: Asset>(&self, label: &Q) -> Option<Handle<B>>
 | |
|     where
 | |
|         CowArc<'static, str>: Borrow<Q>,
 | |
|         Q: ?Sized + Hash + Eq,
 | |
|     {
 | |
|         let labeled = self.labeled_assets.get(label)?;
 | |
|         if let Ok(handle) = labeled.handle.clone().try_typed::<B>() {
 | |
|             return Some(handle);
 | |
|         }
 | |
|         None
 | |
|     }
 | |
|     /// Adds `asset` as a labeled sub asset using `label` and `handle`
 | |
|     pub fn insert_labeled(
 | |
|         &mut self,
 | |
|         label: impl Into<CowArc<'static, str>>,
 | |
|         handle: impl Into<UntypedHandle>,
 | |
|         asset: impl Into<ErasedLoadedAsset>,
 | |
|     ) {
 | |
|         let labeled = LabeledAsset {
 | |
|             asset: asset.into(),
 | |
|             handle: handle.into(),
 | |
|         };
 | |
|         self.labeled_assets.insert(label.into(), labeled);
 | |
|     }
 | |
|     /// Iterate over all labels for "labeled assets" in the loaded asset
 | |
|     pub fn iter_labels(&self) -> impl Iterator<Item = &str> {
 | |
|         self.labeled_assets.keys().map(|s| &**s)
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// An identity [`AssetTransformer`] which infallibly returns the input [`Asset`] on transformation.]
 | |
| pub struct IdentityAssetTransformer<A: Asset> {
 | |
|     _phantom: PhantomData<fn(A) -> A>,
 | |
| }
 | |
| 
 | |
| impl<A: Asset> IdentityAssetTransformer<A> {
 | |
|     pub const fn new() -> Self {
 | |
|         Self {
 | |
|             _phantom: PhantomData,
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl<A: Asset> Default for IdentityAssetTransformer<A> {
 | |
|     fn default() -> Self {
 | |
|         Self::new()
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl<A: Asset> AssetTransformer for IdentityAssetTransformer<A> {
 | |
|     type AssetInput = A;
 | |
|     type AssetOutput = A;
 | |
|     type Settings = ();
 | |
|     type Error = Infallible;
 | |
| 
 | |
|     async fn transform<'a>(
 | |
|         &'a self,
 | |
|         asset: TransformedAsset<Self::AssetInput>,
 | |
|         _settings: &'a Self::Settings,
 | |
|     ) -> Result<TransformedAsset<Self::AssetOutput>, Self::Error> {
 | |
|         Ok(asset)
 | |
|     }
 | |
| }
 |