Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

return type-erased Errors in AssetLoader::load #10463

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions crates/bevy_asset/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ pub enum AssetMode {
///
/// When developing an app, you should enable the `asset_processor` cargo feature, which will run the asset processor at startup. This should generally
/// be used in combination with the `file_watcher` cargo feature, which enables hot-reloading of assets that have changed. When both features are enabled,
/// changes to "original/source assets" will be detected, the asset will be re-processed, and then the final processed asset will be hot-reloaded in the app.
/// changes to "original/source assets" will be detected, the asset will be re-processed, and then the final processed asset will be hot-reloaded in the app.
///
/// [`AssetMeta`]: crate::meta::AssetMeta
/// [`AssetSource`]: crate::io::AssetSource
Expand Down Expand Up @@ -459,22 +459,20 @@ mod tests {

type Settings = ();

type Error = CoolTextLoaderError;

fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a Self::Settings,
load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
) -> BoxedFuture<'a, Result<Self::Asset, crate::BoxedError>> {
Box::pin(async move {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
let mut ron: CoolTextRon = ron::de::from_bytes(&bytes)?;
let mut embedded = String::new();
for dep in ron.embedded_dependencies {
let loaded = load_context.load_direct(&dep).await.map_err(|_| {
Self::Error::CannotLoadDependency {
CoolTextLoaderError::CannotLoadDependency {
dependency: dep.into(),
}
})?;
Expand Down
20 changes: 7 additions & 13 deletions crates/bevy_asset/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,22 @@ use std::{
};
use thiserror::Error;

pub type BoxedError = Box<dyn std::error::Error + Send + Sync>;

/// Loads an [`Asset`] from a given byte [`Reader`]. This can accept [`AssetLoader::Settings`], which configure how the [`Asset`]
/// should be loaded.
pub trait AssetLoader: Send + Sync + 'static {
/// The top level [`Asset`] loaded by this [`AssetLoader`].
type Asset: crate::Asset;
/// The settings type used by this [`AssetLoader`].
type Settings: Settings + Default + Serialize + for<'a> Deserialize<'a>;
/// The type of [error](`std::error::Error`) which could be encountered by this loader.
type Error: std::error::Error + Send + Sync + 'static;
/// Asynchronously loads [`AssetLoader::Asset`] (and any other labeled assets) from the bytes provided by [`Reader`].
fn load<'a>(
&'a self,
reader: &'a mut Reader,
settings: &'a Self::Settings,
load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>>;
) -> BoxedFuture<'a, Result<Self::Asset, BoxedError>>;

/// Returns a list of extensions supported by this asset loader, without the preceding dot.
fn extensions(&self) -> &[&str];
Expand All @@ -49,10 +49,7 @@ pub trait ErasedAssetLoader: Send + Sync + 'static {
reader: &'a mut Reader,
meta: Box<dyn AssetMetaDyn>,
load_context: LoadContext<'a>,
) -> BoxedFuture<
'a,
Result<ErasedLoadedAsset, Box<dyn std::error::Error + Send + Sync + 'static>>,
>;
) -> BoxedFuture<'a, Result<ErasedLoadedAsset, BoxedError>>;

/// Returns a list of extensions supported by this asset loader, without the preceding dot.
fn extensions(&self) -> &[&str];
Expand Down Expand Up @@ -80,10 +77,7 @@ where
reader: &'a mut Reader,
meta: Box<dyn AssetMetaDyn>,
mut load_context: LoadContext<'a>,
) -> BoxedFuture<
'a,
Result<ErasedLoadedAsset, Box<dyn std::error::Error + Send + Sync + 'static>>,
> {
) -> BoxedFuture<'a, Result<ErasedLoadedAsset, BoxedError>> {
Box::pin(async move {
let settings = meta
.loader_settings()
Expand Down Expand Up @@ -446,7 +440,7 @@ impl<'a> LoadContext<'a> {
/// Retrieves a handle for the asset at the given path and adds that path as a dependency of the asset.
/// If the current context is a normal [`AssetServer::load`], an actual asset load will be kicked off immediately, which ensures the load happens
/// as soon as possible.
/// "Normal loads" kicked from within a normal Bevy App will generally configure the context to kick off loads immediately.
/// "Normal loads" kicked from within a normal Bevy App will generally configure the context to kick off loads immediately.
/// If the current context is configured to not load dependencies automatically (ex: [`AssetProcessor`](crate::processor::AssetProcessor)),
/// a load will not be kicked off automatically. It is then the calling context's responsibility to begin a load if necessary.
pub fn load<'b, A: Asset>(&mut self, path: impl Into<AssetPath<'b>>) -> Handle<A> {
Expand All @@ -462,7 +456,7 @@ impl<'a> LoadContext<'a> {

/// Loads the [`Asset`] of type `A` at the given `path` with the given [`AssetLoader::Settings`] settings `S`. This is a "deferred"
/// load. If the settings type `S` does not match the settings expected by `A`'s asset loader, an error will be printed to the log
/// and the asset load will fail.
/// and the asset load will fail.
pub fn load_with_settings<'b, A: Asset, S: Settings + Default>(
&mut self,
path: impl Into<AssetPath<'b>>,
Expand Down
3 changes: 1 addition & 2 deletions crates/bevy_asset/src/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,12 @@ impl VisitAssetDependencies for () {
impl AssetLoader for () {
type Asset = ();
type Settings = ();
type Error = std::io::Error;
fn load<'a>(
&'a self,
_reader: &'a mut crate::io::Reader,
_settings: &'a Self::Settings,
_load_context: &'a mut crate::LoadContext,
) -> bevy_utils::BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
) -> bevy_utils::BoxedFuture<'a, Result<Self::Asset, crate::BoxedError>> {
unreachable!();
}

Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_asset/src/processor/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ pub enum ProcessError {
#[error("The wrong meta type was passed into a processor. This is probably an internal implementation error.")]
WrongMetaType,
#[error("Encountered an error while saving the asset: {0}")]
AssetSaveError(#[from] Box<dyn std::error::Error + Send + Sync + 'static>),
AssetSaveError(#[from] crate::BoxedError),
#[error("Assets without extensions are not supported.")]
ExtensionRequired,
}
Expand Down Expand Up @@ -138,7 +138,7 @@ impl<Loader: AssetLoader, Saver: AssetSaver<Asset = Loader::Asset>> Process
.saver
.save(writer, saved_asset, &settings.saver_settings)
.await
.map_err(|error| ProcessError::AssetSaveError(Box::new(error)))?;
.map_err(ProcessError::AssetSaveError)?;
Ok(output_settings)
})
}
Expand Down
12 changes: 5 additions & 7 deletions crates/bevy_asset/src/saver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,27 @@ pub trait AssetSaver: Send + Sync + 'static {
type Settings: Settings + Default + Serialize + for<'a> Deserialize<'a>;
/// The type of [`AssetLoader`] used to load this [`Asset`]
type OutputLoader: AssetLoader;
/// The type of [error](`std::error::Error`) which could be encountered by this saver.
type Error: std::error::Error + Send + Sync + 'static;

/// Saves the given runtime [`Asset`] by writing it to a byte format using `writer`. The passed in `settings` can influence how the
/// `asset` is saved.
/// `asset` is saved.
fn save<'a>(
&'a self,
writer: &'a mut Writer,
asset: SavedAsset<'a, Self::Asset>,
settings: &'a Self::Settings,
) -> BoxedFuture<'a, Result<<Self::OutputLoader as AssetLoader>::Settings, Self::Error>>;
) -> BoxedFuture<'a, Result<<Self::OutputLoader as AssetLoader>::Settings, crate::BoxedError>>;
}

/// A type-erased dynamic variant of [`AssetSaver`] that allows callers to save assets without knowing the actual type of the [`AssetSaver`].
pub trait ErasedAssetSaver: Send + Sync + 'static {
/// Saves the given runtime [`ErasedLoadedAsset`] by writing it to a byte format using `writer`. The passed in `settings` can influence how the
/// `asset` is saved.
/// `asset` is saved.
fn save<'a>(
&'a self,
writer: &'a mut Writer,
asset: &'a ErasedLoadedAsset,
settings: &'a dyn Settings,
) -> BoxedFuture<'a, Result<(), Box<dyn std::error::Error + Send + Sync + 'static>>>;
) -> BoxedFuture<'a, Result<(), crate::BoxedError>>;

/// The type name of the [`AssetSaver`].
fn type_name(&self) -> &'static str;
Expand All @@ -47,7 +45,7 @@ impl<S: AssetSaver> ErasedAssetSaver for S {
writer: &'a mut Writer,
asset: &'a ErasedLoadedAsset,
settings: &'a dyn Settings,
) -> BoxedFuture<'a, Result<(), Box<dyn std::error::Error + Send + Sync + 'static>>> {
) -> BoxedFuture<'a, Result<(), crate::BoxedError>> {
Box::pin(async move {
let settings = settings
.downcast_ref::<S::Settings>()
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_asset/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use thiserror::Error;
/// The general process to load an asset is:
/// 1. Initialize a new [`Asset`] type with the [`AssetServer`] via [`AssetApp::init_asset`], which will internally call [`AssetServer::register_asset`]
/// and set up related ECS [`Assets`] storage and systems.
/// 2. Register one or more [`AssetLoader`]s for that asset with [`AssetApp::init_asset_loader`]
/// 2. Register one or more [`AssetLoader`]s for that asset with [`AssetApp::init_asset_loader`]
/// 3. Add the asset to your asset folder (defaults to `assets`).
/// 4. Call [`AssetServer::load`] with a path to your asset.
///
Expand Down Expand Up @@ -957,7 +957,7 @@ enum MaybeAssetLoader {
},
}

/// Internal events for asset load results
/// Internal events for asset load results
#[allow(clippy::large_enum_variant)]
pub(crate) enum InternalAssetEvent {
Loaded {
Expand Down Expand Up @@ -1046,7 +1046,7 @@ pub enum AssetLoadError {
AssetLoaderError {
path: AssetPath<'static>,
loader_name: &'static str,
error: Box<dyn std::error::Error + Send + Sync + 'static>,
error: crate::BoxedError,
},
#[error("The file at '{base_path}' does not contain the labeled asset '{label}'.")]
MissingLabel {
Expand Down
5 changes: 2 additions & 3 deletions crates/bevy_audio/src/audio_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,13 @@ pub struct AudioLoader;
impl AssetLoader for AudioLoader {
type Asset = AudioSource;
type Settings = ();
type Error = std::io::Error;

fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a Self::Settings,
_load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<AudioSource, Self::Error>> {
) -> BoxedFuture<'a, Result<AudioSource, bevy_asset::BoxedError>> {
Box::pin(async move {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
Expand Down Expand Up @@ -113,7 +112,7 @@ pub trait AddAudioSource {
/// so that it can be converted to a [`rodio::Source`] type,
/// and [`Asset`], so that it can be registered as an asset.
/// To use this method on [`App`][bevy_app::App],
/// the [audio][super::AudioPlugin] and [asset][bevy_asset::AssetPlugin] plugins must be added first.
/// the [audio][super::AudioPlugin] and [asset][bevy_asset::AssetPlugin] plugins must be added first.
fn add_audio_source<T>(&mut self) -> &mut Self
where
T: Decodable + Asset,
Expand Down
5 changes: 2 additions & 3 deletions crates/bevy_gltf/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,16 @@ pub struct GltfLoader {
impl AssetLoader for GltfLoader {
type Asset = Gltf;
type Settings = ();
type Error = GltfError;
fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a (),
load_context: &'a mut LoadContext,
) -> bevy_utils::BoxedFuture<'a, Result<Gltf, Self::Error>> {
) -> bevy_utils::BoxedFuture<'a, Result<Gltf, bevy_asset::BoxedError>> {
Box::pin(async move {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
load_gltf(self, &bytes, load_context).await
Ok(load_gltf(self, &bytes, load_context).await?)
})
}

Expand Down
3 changes: 1 addition & 2 deletions crates/bevy_render/src/render_resource/shader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,13 +250,12 @@ pub enum ShaderLoaderError {
impl AssetLoader for ShaderLoader {
type Asset = Shader;
type Settings = ();
type Error = ShaderLoaderError;
fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a Self::Settings,
load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Shader, Self::Error>> {
) -> BoxedFuture<'a, Result<Shader, bevy_asset::BoxedError>> {
Box::pin(async move {
let ext = load_context.path().extension().unwrap().to_str().unwrap();

Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_render/src/texture/compressed_image_saver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ impl AssetSaver for CompressedImageSaver {

type Settings = ();
type OutputLoader = ImageLoader;
type Error = CompressedImageSaverError;

fn save<'a>(
&'a self,
writer: &'a mut bevy_asset::io::Writer,
image: SavedAsset<'a, Self::Asset>,
_settings: &'a Self::Settings,
) -> bevy_utils::BoxedFuture<'a, std::result::Result<ImageLoaderSettings, Self::Error>> {
) -> bevy_utils::BoxedFuture<'a, std::result::Result<ImageLoaderSettings, bevy_asset::BoxedError>>
{
// PERF: this should live inside the future, but CompressorParams and Compressor are not Send / can't be owned by the BoxedFuture (which _is_ Send)
let mut compressor_params = basis_universal::CompressorParams::new();
compressor_params.set_basis_format(basis_universal::BasisTextureFormat::UASTC4x4);
Expand Down
3 changes: 1 addition & 2 deletions crates/bevy_render/src/texture/exr_texture_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,13 @@ pub enum ExrTextureLoaderError {
impl AssetLoader for ExrTextureLoader {
type Asset = Image;
type Settings = ();
type Error = ExrTextureLoaderError;

fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a Self::Settings,
_load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Image, Self::Error>> {
) -> BoxedFuture<'a, Result<Image, bevy_asset::BoxedError>> {
Box::pin(async move {
let format = TextureFormat::Rgba32Float;
debug_assert_eq!(
Expand Down
3 changes: 1 addition & 2 deletions crates/bevy_render/src/texture/hdr_texture_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ pub enum HdrTextureLoaderError {
impl AssetLoader for HdrTextureLoader {
type Asset = Image;
type Settings = ();
type Error = HdrTextureLoaderError;
fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a (),
_load_context: &'a mut LoadContext,
) -> bevy_utils::BoxedFuture<'a, Result<Image, Self::Error>> {
) -> bevy_utils::BoxedFuture<'a, Result<Image, bevy_asset::BoxedError>> {
Box::pin(async move {
let format = TextureFormat::Rgba32Float;
debug_assert_eq!(
Expand Down
3 changes: 1 addition & 2 deletions crates/bevy_render/src/texture/image_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,12 @@ pub enum ImageLoaderError {
impl AssetLoader for ImageLoader {
type Asset = Image;
type Settings = ImageLoaderSettings;
type Error = ImageLoaderError;
fn load<'a>(
&'a self,
reader: &'a mut Reader,
settings: &'a ImageLoaderSettings,
load_context: &'a mut LoadContext,
) -> bevy_utils::BoxedFuture<'a, Result<Image, Self::Error>> {
) -> bevy_utils::BoxedFuture<'a, Result<Image, bevy_asset::BoxedError>> {
Box::pin(async move {
// use the file extension for the image type
let ext = load_context.path().extension().unwrap().to_str().unwrap();
Expand Down
3 changes: 1 addition & 2 deletions crates/bevy_scene/src/scene_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,13 @@ pub enum SceneLoaderError {
impl AssetLoader for SceneLoader {
type Asset = DynamicScene;
type Settings = ();
type Error = SceneLoaderError;

fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a (),
_load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
) -> BoxedFuture<'a, Result<Self::Asset, bevy_asset::BoxedError>> {
Box::pin(async move {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
Expand Down
3 changes: 1 addition & 2 deletions crates/bevy_text/src/font_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,12 @@ pub enum FontLoaderError {
impl AssetLoader for FontLoader {
type Asset = Font;
type Settings = ();
type Error = FontLoaderError;
fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a (),
_load_context: &'a mut LoadContext,
) -> bevy_utils::BoxedFuture<'a, Result<Font, Self::Error>> {
) -> bevy_utils::BoxedFuture<'a, Result<Font, bevy_asset::BoxedError>> {
Box::pin(async move {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
Expand Down
3 changes: 1 addition & 2 deletions examples/asset/custom_asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@ pub enum CustomAssetLoaderError {
impl AssetLoader for CustomAssetLoader {
type Asset = CustomAsset;
type Settings = ();
type Error = CustomAssetLoaderError;
fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a (),
_load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
) -> BoxedFuture<'a, Result<Self::Asset, bevy::asset::BoxedError>> {
Box::pin(async move {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
Expand Down
Loading