Skip to content

Commit

Permalink
Improve error handling for AssetServer::add_async (#13745)
Browse files Browse the repository at this point in the history
# Objective

The method `AssetServer::add_async` (added in
#13700) requires a future that
returns an `AssetLoadError` error, which was a bit of an oversight on my
part, as that type of error only really makes sense in the context of
bevy's own asset loader -- returning it from user-defined futures isn't
very useful.

## Solution

Allow passing custom error types to `add_async`, which get cast into a
trait object matching the form of `AssetLoader::load`. If merged before
the next release this will not be a breaking change
  • Loading branch information
JoJoJet authored Jun 10, 2024
1 parent a569b35 commit 0dfdd87
Showing 1 changed file with 24 additions and 3 deletions.
27 changes: 24 additions & 3 deletions crates/bevy_asset/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -718,9 +718,9 @@ impl AssetServer {
///
/// After the asset has been fully loaded, it will show up in the relevant [`Assets`] storage.
#[must_use = "not using the returned strong handle may result in the unexpected release of the asset"]
pub fn add_async<A: Asset>(
pub fn add_async<A: Asset, E: std::error::Error + Send + Sync + 'static>(
&self,
future: impl Future<Output = Result<A, AssetLoadError>> + Send + 'static,
future: impl Future<Output = Result<A, E>> + Send + 'static,
) -> Handle<A> {
let handle = self
.data
Expand All @@ -741,12 +741,15 @@ impl AssetServer {
.unwrap();
}
Err(error) => {
let error = AddAsyncError {
error: Arc::new(error),
};
error!("{error}");
event_sender
.send(InternalAssetEvent::Failed {
id,
path: Default::default(),
error,
error: AssetLoadError::AddAsyncError(error),
})
.unwrap();
}
Expand Down Expand Up @@ -1403,6 +1406,8 @@ pub enum AssetLoadError {
CannotLoadIgnoredAsset { path: AssetPath<'static> },
#[error(transparent)]
AssetLoaderError(#[from] AssetLoaderError),
#[error(transparent)]
AddAsyncError(#[from] AddAsyncError),
#[error("The file at '{}' does not contain the labeled asset '{}'; it contains the following {} assets: {}",
base_path,
label,
Expand Down Expand Up @@ -1441,6 +1446,22 @@ impl AssetLoaderError {
}
}

#[derive(Error, Debug, Clone)]
#[error("An error occurred while resolving an asset added by `add_async`: {error}")]
pub struct AddAsyncError {
error: Arc<dyn std::error::Error + Send + Sync + 'static>,
}

impl PartialEq for AddAsyncError {
/// Equality comparison is not full (only through `TypeId`)
#[inline]
fn eq(&self, other: &Self) -> bool {
self.error.type_id() == other.error.type_id()
}
}

impl Eq for AddAsyncError {}

/// An error that occurs when an [`AssetLoader`] is not registered for a given extension.
#[derive(Error, Debug, Clone, PartialEq, Eq)]
#[error("no `AssetLoader` found{}", format_missing_asset_ext(.extensions))]
Expand Down

0 comments on commit 0dfdd87

Please sign in to comment.