
# 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"]
|
|
}
|
|
}
|