 dd46fd3aee
			
		
	
	
		dd46fd3aee
		
			
		
	
	
	
	
		
			
			# Objective - Fixes #8140 ## Solution - Added Explicit Error Typing for `AssetLoader` and `AssetSaver`, which were the last instances of `anyhow` in use across Bevy. --- ## Changelog - Added an associated type `Error` to `AssetLoader` and `AssetSaver` for use with the `load` and `save` methods respectively. - Changed `ErasedAssetLoader` and `ErasedAssetSaver` `load` and `save` methods to use `Box<dyn Error + Send + Sync + 'static>` to allow for arbitrary `Error` types from the non-erased trait variants. Note the strict requirements match the pre-existing requirements around `anyhow::Error`. ## Migration Guide - `anyhow` is no longer exported by `bevy_asset`; Add it to your own project (if required). - `AssetLoader` and `AssetSaver` have an associated type `Error`; Define an appropriate error type (e.g., using `thiserror`), or use a pre-made error type (e.g., `anyhow::Error`). Note that using `anyhow::Error` is a drop-in replacement. - `AssetLoaderError` has been removed; Define a new error type, or use an alternative (e.g., `anyhow::Error`) - All the first-party `AssetLoader`'s and `AssetSaver`'s now return relevant (and narrow) error types instead of a single ambiguous type; Match over the specific error type, or encapsulate (`Box<dyn>`, `thiserror`, `anyhow`, etc.) ## Notes A simpler PR to resolve this issue would simply define a Bevy `Error` type defined as `Box<dyn std::error::Error + Send + Sync + 'static>`, but I think this type of error handling should be discouraged when possible. Since only 2 traits required the use of `anyhow`, it isn't a substantive body of work to solidify these error types, and remove `anyhow` entirely. End users are still encouraged to use `anyhow` if that is their preferred error handling style. Arguably, adding the `Error` associated type gives more freedom to end-users to decide whether they want more or less explicit error handling (`anyhow` vs `thiserror`). As an aside, I didn't perform any testing on Android or WASM. CI passed locally, but there may be mistakes for those platforms I missed.
		
			
				
	
	
		
			41 lines
		
	
	
		
			1.0 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			41 lines
		
	
	
		
			1.0 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use crate::Font;
 | |
| use bevy_asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext};
 | |
| use thiserror::Error;
 | |
| 
 | |
| #[derive(Default)]
 | |
| pub struct FontLoader;
 | |
| 
 | |
| /// Possible errors that can be produced by [`FontLoader`]
 | |
| #[non_exhaustive]
 | |
| #[derive(Debug, Error)]
 | |
| pub enum FontLoaderError {
 | |
|     /// An [IO](std::io) Error
 | |
|     #[error(transparent)]
 | |
|     Io(#[from] std::io::Error),
 | |
|     /// An [InvalidFont](ab_glyph::InvalidFont) Error
 | |
|     #[error(transparent)]
 | |
|     FontInvalid(#[from] ab_glyph::InvalidFont),
 | |
| }
 | |
| 
 | |
| 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>> {
 | |
|         Box::pin(async move {
 | |
|             let mut bytes = Vec::new();
 | |
|             reader.read_to_end(&mut bytes).await?;
 | |
|             Ok(Font::try_from_bytes(bytes)?)
 | |
|         })
 | |
|     }
 | |
| 
 | |
|     fn extensions(&self) -> &[&str] {
 | |
|         &["ttf", "otf"]
 | |
|     }
 | |
| }
 |