Remove thiserror from bevy_asset (#15778)

# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_asset`
This commit is contained in:
Zachary Harrold 2024-10-10 01:30:46 +11:00 committed by GitHub
parent ecd04c1b72
commit 35edb256ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 162 additions and 179 deletions

View File

@ -44,7 +44,11 @@ blake3 = "1.5"
parking_lot = { version = "0.12", features = ["arc_lock", "send_guard"] } parking_lot = { version = "0.12", features = ["arc_lock", "send_guard"] }
ron = "0.8" ron = "0.8"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
thiserror = "1.0" derive_more = { version = "1", default-features = false, features = [
"error",
"from",
"display",
] }
uuid = { version = "1.0", features = ["v4"] } uuid = { version = "1.0", features = ["v4"] }
[target.'cfg(target_os = "android")'.dependencies] [target.'cfg(target_os = "android")'.dependencies]

View File

@ -11,8 +11,8 @@ use bevy_reflect::{Reflect, TypePath};
use bevy_utils::HashMap; use bevy_utils::HashMap;
use core::{any::TypeId, iter::Enumerate, marker::PhantomData, sync::atomic::AtomicU32}; use core::{any::TypeId, iter::Enumerate, marker::PhantomData, sync::atomic::AtomicU32};
use crossbeam_channel::{Receiver, Sender}; use crossbeam_channel::{Receiver, Sender};
use derive_more::derive::{Display, Error};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use thiserror::Error;
use uuid::Uuid; use uuid::Uuid;
/// A generational runtime-only identifier for a specific [`Asset`] stored in [`Assets`]. This is optimized for efficient runtime /// A generational runtime-only identifier for a specific [`Asset`] stored in [`Assets`]. This is optimized for efficient runtime
@ -613,8 +613,8 @@ impl<'a, A: Asset> Iterator for AssetsMutIterator<'a, A> {
} }
} }
#[derive(Error, Debug)] #[derive(Error, Display, Debug)]
#[error("AssetIndex {index:?} has an invalid generation. The current generation is: '{current_generation}'.")] #[display("AssetIndex {index:?} has an invalid generation. The current generation is: '{current_generation}'.")]
pub struct InvalidGenerationError { pub struct InvalidGenerationError {
index: AssetIndex, index: AssetIndex,
current_generation: u32, current_generation: u32,

View File

@ -10,8 +10,8 @@ use core::{
hash::{Hash, Hasher}, hash::{Hash, Hasher},
}; };
use crossbeam_channel::{Receiver, Sender}; use crossbeam_channel::{Receiver, Sender};
use derive_more::derive::{Display, Error};
use disqualified::ShortName; use disqualified::ShortName;
use thiserror::Error;
use uuid::Uuid; use uuid::Uuid;
/// Provides [`Handle`] and [`UntypedHandle`] _for a specific asset type_. /// Provides [`Handle`] and [`UntypedHandle`] _for a specific asset type_.
@ -503,11 +503,11 @@ impl<A: Asset> TryFrom<UntypedHandle> for Handle<A> {
} }
/// Errors preventing the conversion of to/from an [`UntypedHandle`] and a [`Handle`]. /// Errors preventing the conversion of to/from an [`UntypedHandle`] and a [`Handle`].
#[derive(Error, Debug, PartialEq, Clone)] #[derive(Error, Display, Debug, PartialEq, Clone)]
#[non_exhaustive] #[non_exhaustive]
pub enum UntypedAssetConversionError { pub enum UntypedAssetConversionError {
/// Caused when trying to convert an [`UntypedHandle`] into a [`Handle`] of the wrong type. /// Caused when trying to convert an [`UntypedHandle`] into a [`Handle`] of the wrong type.
#[error( #[display(
"This UntypedHandle is for {found:?} and cannot be converted into a Handle<{expected:?}>" "This UntypedHandle is for {found:?} and cannot be converted into a Handle<{expected:?}>"
)] )]
TypeIdMismatch { expected: TypeId, found: TypeId }, TypeIdMismatch { expected: TypeId, found: TypeId },

View File

@ -9,7 +9,7 @@ use core::{
hash::Hash, hash::Hash,
marker::PhantomData, marker::PhantomData,
}; };
use thiserror::Error; use derive_more::derive::{Display, Error, From};
/// A unique runtime-only identifier for an [`Asset`]. This is cheap to [`Copy`]/[`Clone`] and is not directly tied to the /// A unique runtime-only identifier for an [`Asset`]. This is cheap to [`Copy`]/[`Clone`] and is not directly tied to the
/// lifetime of the Asset. This means it _can_ point to an [`Asset`] that no longer exists. /// lifetime of the Asset. This means it _can_ point to an [`Asset`] that no longer exists.
@ -17,7 +17,7 @@ use thiserror::Error;
/// For an identifier tied to the lifetime of an asset, see [`Handle`](`crate::Handle`). /// For an identifier tied to the lifetime of an asset, see [`Handle`](`crate::Handle`).
/// ///
/// For an "untyped" / "generic-less" id, see [`UntypedAssetId`]. /// For an "untyped" / "generic-less" id, see [`UntypedAssetId`].
#[derive(Reflect, Serialize, Deserialize)] #[derive(Reflect, Serialize, Deserialize, From)]
pub enum AssetId<A: Asset> { pub enum AssetId<A: Asset> {
/// A small / efficient runtime identifier that can be used to efficiently look up an asset stored in [`Assets`]. This is /// A small / efficient runtime identifier that can be used to efficiently look up an asset stored in [`Assets`]. This is
/// the "default" identifier used for assets. The alternative(s) (ex: [`AssetId::Uuid`]) will only be used if assets are /// the "default" identifier used for assets. The alternative(s) (ex: [`AssetId::Uuid`]) will only be used if assets are
@ -154,13 +154,6 @@ impl<A: Asset> From<AssetIndex> for AssetId<A> {
} }
} }
impl<A: Asset> From<Uuid> for AssetId<A> {
#[inline]
fn from(value: Uuid) -> Self {
Self::Uuid { uuid: value }
}
}
/// An "untyped" / "generic-less" [`Asset`] identifier that behaves much like [`AssetId`], but stores the [`Asset`] type /// An "untyped" / "generic-less" [`Asset`] identifier that behaves much like [`AssetId`], but stores the [`Asset`] type
/// information at runtime instead of compile-time. This increases the size of the type, but it enables storing asset ids /// information at runtime instead of compile-time. This increases the size of the type, but it enables storing asset ids
/// across asset types together and enables comparisons between them. /// across asset types together and enables comparisons between them.
@ -310,7 +303,7 @@ impl PartialOrd for UntypedAssetId {
/// Do not _ever_ use this across asset types for comparison. /// Do not _ever_ use this across asset types for comparison.
/// [`InternalAssetId`] contains no type information and will happily collide /// [`InternalAssetId`] contains no type information and will happily collide
/// with indices across types. /// with indices across types.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord, From)]
pub(crate) enum InternalAssetId { pub(crate) enum InternalAssetId {
Index(AssetIndex), Index(AssetIndex),
Uuid(Uuid), Uuid(Uuid),
@ -337,18 +330,6 @@ impl InternalAssetId {
} }
} }
impl From<AssetIndex> for InternalAssetId {
fn from(value: AssetIndex) -> Self {
Self::Index(value)
}
}
impl From<Uuid> for InternalAssetId {
fn from(value: Uuid) -> Self {
Self::Uuid(value)
}
}
// Cross Operations // Cross Operations
impl<A: Asset> PartialEq<UntypedAssetId> for AssetId<A> { impl<A: Asset> PartialEq<UntypedAssetId> for AssetId<A> {
@ -417,11 +398,11 @@ impl<A: Asset> TryFrom<UntypedAssetId> for AssetId<A> {
} }
/// Errors preventing the conversion of to/from an [`UntypedAssetId`] and an [`AssetId`]. /// Errors preventing the conversion of to/from an [`UntypedAssetId`] and an [`AssetId`].
#[derive(Error, Debug, PartialEq, Clone)] #[derive(Error, Display, Debug, PartialEq, Clone)]
#[non_exhaustive] #[non_exhaustive]
pub enum UntypedAssetIdConversionError { pub enum UntypedAssetIdConversionError {
/// Caused when trying to convert an [`UntypedAssetId`] into an [`AssetId`] of the wrong type. /// Caused when trying to convert an [`UntypedAssetId`] into an [`AssetId`] of the wrong type.
#[error("This UntypedAssetId is for {found:?} and cannot be converted into an AssetId<{expected:?}>")] #[display("This UntypedAssetId is for {found:?} and cannot be converted into an AssetId<{expected:?}>")]
TypeIdMismatch { expected: TypeId, found: TypeId }, TypeIdMismatch { expected: TypeId, found: TypeId },
} }

View File

@ -28,25 +28,27 @@ use core::{
pin::Pin, pin::Pin,
task::{Context, Poll}, task::{Context, Poll},
}; };
use derive_more::derive::{Display, Error, From};
use futures_io::{AsyncRead, AsyncWrite}; use futures_io::{AsyncRead, AsyncWrite};
use futures_lite::{ready, Stream}; use futures_lite::{ready, Stream};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use thiserror::Error;
/// Errors that occur while loading assets. /// Errors that occur while loading assets.
#[derive(Error, Debug, Clone)] #[derive(Error, Display, Debug, Clone)]
pub enum AssetReaderError { pub enum AssetReaderError {
/// Path not found. /// Path not found.
#[error("Path not found: {0}")] #[display("Path not found: {}", _0.display())]
#[error(ignore)]
NotFound(PathBuf), NotFound(PathBuf),
/// Encountered an I/O error while loading an asset. /// Encountered an I/O error while loading an asset.
#[error("Encountered an I/O error while loading asset: {0}")] #[display("Encountered an I/O error while loading asset: {_0}")]
Io(Arc<std::io::Error>), Io(Arc<std::io::Error>),
/// The HTTP request completed but returned an unhandled [HTTP response status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status). /// The HTTP request completed but returned an unhandled [HTTP response status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status).
/// If the request fails before getting a status code (e.g. request timeout, interrupted connection, etc), expect [`AssetReaderError::Io`]. /// If the request fails before getting a status code (e.g. request timeout, interrupted connection, etc), expect [`AssetReaderError::Io`].
#[error("Encountered HTTP status {0:?} when loading asset")] #[display("Encountered HTTP status {_0:?} when loading asset")]
#[error(ignore)]
HttpError(u16), HttpError(u16),
} }
@ -296,11 +298,11 @@ pub type Writer = dyn AsyncWrite + Unpin + Send + Sync;
pub type PathStream = dyn Stream<Item = PathBuf> + Unpin + Send; pub type PathStream = dyn Stream<Item = PathBuf> + Unpin + Send;
/// Errors that occur while loading assets. /// Errors that occur while loading assets.
#[derive(Error, Debug)] #[derive(Error, Display, Debug, From)]
pub enum AssetWriterError { pub enum AssetWriterError {
/// Encountered an I/O error while loading an asset. /// Encountered an I/O error while loading an asset.
#[error("encountered an io error while loading asset: {0}")] #[display("encountered an io error while loading asset: {_0}")]
Io(#[from] std::io::Error), Io(std::io::Error),
} }
/// Preforms write operations on an asset storage. [`AssetWriter`] exposes a "virtual filesystem" /// Preforms write operations on an asset storage. [`AssetWriter`] exposes a "virtual filesystem"

View File

@ -10,7 +10,7 @@ use bevy_utils::{
Duration, HashMap, Duration, HashMap,
}; };
use core::{fmt::Display, hash::Hash}; use core::{fmt::Display, hash::Hash};
use thiserror::Error; use derive_more::derive::{Display, Error};
use super::{ErasedAssetReader, ErasedAssetWriter}; use super::{ErasedAssetReader, ErasedAssetWriter};
@ -629,23 +629,27 @@ impl AssetSources {
} }
/// An error returned when an [`AssetSource`] does not exist for a given id. /// An error returned when an [`AssetSource`] does not exist for a given id.
#[derive(Error, Debug, Clone, PartialEq, Eq)] #[derive(Error, Display, Debug, Clone, PartialEq, Eq)]
#[error("Asset Source '{0}' does not exist")] #[display("Asset Source '{_0}' does not exist")]
#[error(ignore)]
pub struct MissingAssetSourceError(AssetSourceId<'static>); pub struct MissingAssetSourceError(AssetSourceId<'static>);
/// An error returned when an [`AssetWriter`](crate::io::AssetWriter) does not exist for a given id. /// An error returned when an [`AssetWriter`](crate::io::AssetWriter) does not exist for a given id.
#[derive(Error, Debug, Clone)] #[derive(Error, Display, Debug, Clone)]
#[error("Asset Source '{0}' does not have an AssetWriter.")] #[display("Asset Source '{_0}' does not have an AssetWriter.")]
#[error(ignore)]
pub struct MissingAssetWriterError(AssetSourceId<'static>); pub struct MissingAssetWriterError(AssetSourceId<'static>);
/// An error returned when a processed [`AssetReader`](crate::io::AssetReader) does not exist for a given id. /// An error returned when a processed [`AssetReader`](crate::io::AssetReader) does not exist for a given id.
#[derive(Error, Debug, Clone, PartialEq, Eq)] #[derive(Error, Display, Debug, Clone, PartialEq, Eq)]
#[error("Asset Source '{0}' does not have a processed AssetReader.")] #[display("Asset Source '{_0}' does not have a processed AssetReader.")]
#[error(ignore)]
pub struct MissingProcessedAssetReaderError(AssetSourceId<'static>); pub struct MissingProcessedAssetReaderError(AssetSourceId<'static>);
/// An error returned when a processed [`AssetWriter`](crate::io::AssetWriter) does not exist for a given id. /// An error returned when a processed [`AssetWriter`](crate::io::AssetWriter) does not exist for a given id.
#[derive(Error, Debug, Clone)] #[derive(Error, Display, Debug, Clone)]
#[error("Asset Source '{0}' does not have a processed AssetWriter.")] #[display("Asset Source '{_0}' does not have a processed AssetWriter.")]
#[error(ignore)]
pub struct MissingProcessedAssetWriterError(AssetSourceId<'static>); pub struct MissingProcessedAssetWriterError(AssetSourceId<'static>);
const MISSING_DEFAULT_SOURCE: &str = const MISSING_DEFAULT_SOURCE: &str =

View File

@ -631,9 +631,9 @@ mod tests {
use bevy_log::LogPlugin; use bevy_log::LogPlugin;
use bevy_reflect::TypePath; use bevy_reflect::TypePath;
use bevy_utils::{Duration, HashMap}; use bevy_utils::{Duration, HashMap};
use derive_more::derive::{Display, Error, From};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::Path; use std::path::Path;
use thiserror::Error;
#[derive(Asset, TypePath, Debug, Default)] #[derive(Asset, TypePath, Debug, Default)]
pub struct CoolText { pub struct CoolText {
@ -661,14 +661,14 @@ mod tests {
#[derive(Default)] #[derive(Default)]
pub struct CoolTextLoader; pub struct CoolTextLoader;
#[derive(Error, Debug)] #[derive(Error, Display, Debug, From)]
pub enum CoolTextLoaderError { pub enum CoolTextLoaderError {
#[error("Could not load dependency: {dependency}")] #[display("Could not load dependency: {dependency}")]
CannotLoadDependency { dependency: AssetPath<'static> }, CannotLoadDependency { dependency: AssetPath<'static> },
#[error("A RON error occurred during loading")] #[display("A RON error occurred during loading")]
RonSpannedError(#[from] ron::error::SpannedError), RonSpannedError(ron::error::SpannedError),
#[error("An IO error occurred during loading")] #[display("An IO error occurred during loading")]
Io(#[from] std::io::Error), Io(std::io::Error),
} }
impl AssetLoader for CoolTextLoader { impl AssetLoader for CoolTextLoader {

View File

@ -10,11 +10,11 @@ use atomicow::CowArc;
use bevy_ecs::world::World; use bevy_ecs::world::World;
use bevy_utils::{BoxedFuture, ConditionalSendFuture, HashMap, HashSet}; use bevy_utils::{BoxedFuture, ConditionalSendFuture, HashMap, HashSet};
use core::any::{Any, TypeId}; use core::any::{Any, TypeId};
use derive_more::derive::{Display, Error, From};
use downcast_rs::{impl_downcast, Downcast}; use downcast_rs::{impl_downcast, Downcast};
use ron::error::SpannedError; use ron::error::SpannedError;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use thiserror::Error;
/// Loads an [`Asset`] from a given byte [`Reader`]. This can accept [`AssetLoader::Settings`], which configure how the [`Asset`] /// Loads an [`Asset`] from a given byte [`Reader`]. This can accept [`AssetLoader::Settings`], which configure how the [`Asset`]
/// should be loaded. /// should be loaded.
@ -295,19 +295,20 @@ impl<A: Asset> AssetContainer for A {
/// ///
/// [`NestedLoader::load`]: crate::NestedLoader::load /// [`NestedLoader::load`]: crate::NestedLoader::load
/// [immediately]: crate::Immediate /// [immediately]: crate::Immediate
#[derive(Error, Debug)] #[derive(Error, Display, Debug)]
#[error("Failed to load dependency {dependency:?} {error}")] #[display("Failed to load dependency {dependency:?} {error}")]
pub struct LoadDirectError { pub struct LoadDirectError {
pub dependency: AssetPath<'static>, pub dependency: AssetPath<'static>,
pub error: AssetLoadError, pub error: AssetLoadError,
} }
/// An error that occurs while deserializing [`AssetMeta`]. /// An error that occurs while deserializing [`AssetMeta`].
#[derive(Error, Debug, Clone, PartialEq, Eq)] #[derive(Error, Display, Debug, Clone, PartialEq, Eq, From)]
pub enum DeserializeMetaError { pub enum DeserializeMetaError {
#[error("Failed to deserialize asset meta: {0:?}")] #[display("Failed to deserialize asset meta: {_0:?}")]
DeserializeSettings(#[from] SpannedError), DeserializeSettings(SpannedError),
#[error("Failed to deserialize minimal asset meta: {0:?}")] #[display("Failed to deserialize minimal asset meta: {_0:?}")]
#[from(ignore)]
DeserializeMinimal(SpannedError), DeserializeMinimal(SpannedError),
} }
@ -572,23 +573,18 @@ impl<'a> LoadContext<'a> {
} }
/// An error produced when calling [`LoadContext::read_asset_bytes`] /// An error produced when calling [`LoadContext::read_asset_bytes`]
#[derive(Error, Debug)] #[derive(Error, Display, Debug, From)]
pub enum ReadAssetBytesError { pub enum ReadAssetBytesError {
#[error(transparent)] DeserializeMetaError(DeserializeMetaError),
DeserializeMetaError(#[from] DeserializeMetaError), AssetReaderError(AssetReaderError),
#[error(transparent)] MissingAssetSourceError(MissingAssetSourceError),
AssetReaderError(#[from] AssetReaderError), MissingProcessedAssetReaderError(MissingProcessedAssetReaderError),
#[error(transparent)]
MissingAssetSourceError(#[from] MissingAssetSourceError),
#[error(transparent)]
MissingProcessedAssetReaderError(#[from] MissingProcessedAssetReaderError),
/// Encountered an I/O error while loading an asset. /// Encountered an I/O error while loading an asset.
#[error("Encountered an io error while loading asset at `{path}`: {source}")] #[display("Encountered an io error while loading asset at `{}`: {source}", path.display())]
Io { Io {
path: PathBuf, path: PathBuf,
#[source]
source: std::io::Error, source: std::io::Error,
}, },
#[error("The LoadContext for this read_asset_bytes call requires hash metadata, but it was not provided. This is likely an internal implementation error.")] #[display("The LoadContext for this read_asset_bytes call requires hash metadata, but it was not provided. This is likely an internal implementation error.")]
MissingAssetHash, MissingAssetHash,
} }

View File

@ -6,9 +6,9 @@ use core::{
hash::Hash, hash::Hash,
ops::Deref, ops::Deref,
}; };
use derive_more::derive::{Display, Error};
use serde::{de::Visitor, Deserialize, Serialize}; use serde::{de::Visitor, Deserialize, Serialize};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use thiserror::Error;
/// Represents a path to an asset in a "virtual filesystem". /// Represents a path to an asset in a "virtual filesystem".
/// ///
@ -76,19 +76,19 @@ impl<'a> Display for AssetPath<'a> {
} }
/// An error that occurs when parsing a string type to create an [`AssetPath`] fails, such as during [`AssetPath::parse`]. /// An error that occurs when parsing a string type to create an [`AssetPath`] fails, such as during [`AssetPath::parse`].
#[derive(Error, Debug, PartialEq, Eq)] #[derive(Error, Display, Debug, PartialEq, Eq)]
pub enum ParseAssetPathError { pub enum ParseAssetPathError {
/// Error that occurs when the [`AssetPath::source`] section of a path string contains the [`AssetPath::label`] delimiter `#`. E.g. `bad#source://file.test`. /// Error that occurs when the [`AssetPath::source`] section of a path string contains the [`AssetPath::label`] delimiter `#`. E.g. `bad#source://file.test`.
#[error("Asset source must not contain a `#` character")] #[display("Asset source must not contain a `#` character")]
InvalidSourceSyntax, InvalidSourceSyntax,
/// Error that occurs when the [`AssetPath::label`] section of a path string contains the [`AssetPath::source`] delimiter `://`. E.g. `source://file.test#bad://label`. /// Error that occurs when the [`AssetPath::label`] section of a path string contains the [`AssetPath::source`] delimiter `://`. E.g. `source://file.test#bad://label`.
#[error("Asset label must not contain a `://` substring")] #[display("Asset label must not contain a `://` substring")]
InvalidLabelSyntax, InvalidLabelSyntax,
/// Error that occurs when a path string has an [`AssetPath::source`] delimiter `://` with no characters preceding it. E.g. `://file.test`. /// Error that occurs when a path string has an [`AssetPath::source`] delimiter `://` with no characters preceding it. E.g. `://file.test`.
#[error("Asset source must be at least one character. Either specify the source before the '://' or remove the `://`")] #[display("Asset source must be at least one character. Either specify the source before the '://' or remove the `://`")]
MissingSource, MissingSource,
/// Error that occurs when a path string has an [`AssetPath::label`] delimiter `#` with no characters succeeding it. E.g. `file.test#` /// Error that occurs when a path string has an [`AssetPath::label`] delimiter `#` with no characters succeeding it. E.g. `file.test#`
#[error("Asset label must be at least one character. Either specify the label after the '#' or remove the '#'")] #[display("Asset label must be at least one character. Either specify the label after the '#' or remove the '#'")]
MissingLabel, MissingLabel,
} }

View File

@ -1,9 +1,9 @@
use crate::AssetPath; use crate::AssetPath;
use async_fs::File; use async_fs::File;
use bevy_utils::{tracing::error, HashSet}; use bevy_utils::{tracing::error, HashSet};
use derive_more::derive::{Display, Error, From};
use futures_lite::{AsyncReadExt, AsyncWriteExt}; use futures_lite::{AsyncReadExt, AsyncWriteExt};
use std::path::PathBuf; use std::path::PathBuf;
use thiserror::Error;
/// An in-memory representation of a single [`ProcessorTransactionLog`] entry. /// An in-memory representation of a single [`ProcessorTransactionLog`] entry.
#[derive(Debug)] #[derive(Debug)]
@ -24,17 +24,18 @@ pub struct ProcessorTransactionLog {
} }
/// An error that occurs when reading from the [`ProcessorTransactionLog`] fails. /// An error that occurs when reading from the [`ProcessorTransactionLog`] fails.
#[derive(Error, Debug)] #[derive(Error, Display, Debug, From)]
pub enum ReadLogError { pub enum ReadLogError {
#[error("Encountered an invalid log line: '{0}'")] #[display("Encountered an invalid log line: '{_0}'")]
#[error(ignore)]
InvalidLine(String), InvalidLine(String),
#[error("Failed to read log file: {0}")] #[display("Failed to read log file: {_0}")]
Io(#[from] futures_io::Error), Io(futures_io::Error),
} }
/// An error that occurs when writing to the [`ProcessorTransactionLog`] fails. /// An error that occurs when writing to the [`ProcessorTransactionLog`] fails.
#[derive(Error, Debug)] #[derive(Error, Display, Debug)]
#[error( #[display(
"Failed to write {log_entry:?} to the asset processor log. This is not recoverable. {error}" "Failed to write {log_entry:?} to the asset processor log. This is not recoverable. {error}"
)] )]
pub struct WriteLogError { pub struct WriteLogError {
@ -43,24 +44,27 @@ pub struct WriteLogError {
} }
/// An error that occurs when validating the [`ProcessorTransactionLog`] fails. /// An error that occurs when validating the [`ProcessorTransactionLog`] fails.
#[derive(Error, Debug)] #[derive(Error, Display, Debug, From)]
pub enum ValidateLogError { pub enum ValidateLogError {
#[error("Encountered an unrecoverable error. All assets will be reprocessed.")] #[display("Encountered an unrecoverable error. All assets will be reprocessed.")]
UnrecoverableError, UnrecoverableError,
#[error(transparent)] ReadLogError(ReadLogError),
ReadLogError(#[from] ReadLogError), #[display("Encountered a duplicate process asset transaction: {_0:?}")]
#[error("Encountered a duplicate process asset transaction: {0:?}")] #[error(ignore)]
EntryErrors(Vec<LogEntryError>), EntryErrors(Vec<LogEntryError>),
} }
/// An error that occurs when validating individual [`ProcessorTransactionLog`] entries. /// An error that occurs when validating individual [`ProcessorTransactionLog`] entries.
#[derive(Error, Debug)] #[derive(Error, Display, Debug)]
pub enum LogEntryError { pub enum LogEntryError {
#[error("Encountered a duplicate process asset transaction: {0}")] #[display("Encountered a duplicate process asset transaction: {_0}")]
#[error(ignore)]
DuplicateTransaction(AssetPath<'static>), DuplicateTransaction(AssetPath<'static>),
#[error("A transaction was ended that never started {0}")] #[display("A transaction was ended that never started {_0}")]
#[error(ignore)]
EndedMissingTransaction(AssetPath<'static>), EndedMissingTransaction(AssetPath<'static>),
#[error("An asset started processing but never finished: {0}")] #[display("An asset started processing but never finished: {_0}")]
#[error(ignore)]
UnfinishedTransaction(AssetPath<'static>), UnfinishedTransaction(AssetPath<'static>),
} }

View File

@ -68,11 +68,11 @@ use bevy_utils::{
tracing::{info_span, instrument::Instrument}, tracing::{info_span, instrument::Instrument},
ConditionalSendFuture, ConditionalSendFuture,
}; };
use derive_more::derive::{Display, Error};
use futures_io::ErrorKind; use futures_io::ErrorKind;
use futures_lite::{AsyncReadExt, AsyncWriteExt, StreamExt}; use futures_lite::{AsyncReadExt, AsyncWriteExt, StreamExt};
use parking_lot::RwLock; use parking_lot::RwLock;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use thiserror::Error;
/// A "background" asset processor that reads asset values from a source [`AssetSource`] (which corresponds to an [`AssetReader`](crate::io::AssetReader) / [`AssetWriter`](crate::io::AssetWriter) pair), /// A "background" asset processor that reads asset values from a source [`AssetSource`] (which corresponds to an [`AssetReader`](crate::io::AssetReader) / [`AssetWriter`](crate::io::AssetWriter) pair),
/// processes them in some way, and writes them to a destination [`AssetSource`]. /// processes them in some way, and writes them to a destination [`AssetSource`].
@ -1413,12 +1413,10 @@ pub enum ProcessorState {
} }
/// An error that occurs when initializing the [`AssetProcessor`]. /// An error that occurs when initializing the [`AssetProcessor`].
#[derive(Error, Debug)] #[derive(Error, Display, Debug)]
pub enum InitializeError { pub enum InitializeError {
#[error(transparent)]
FailedToReadSourcePaths(AssetReaderError), FailedToReadSourcePaths(AssetReaderError),
#[error(transparent)]
FailedToReadDestinationPaths(AssetReaderError), FailedToReadDestinationPaths(AssetReaderError),
#[error("Failed to validate asset log: {0}")] #[display("Failed to validate asset log: {_0}")]
ValidateLogError(ValidateLogError), ValidateLogError(ValidateLogError),
} }

View File

@ -12,8 +12,8 @@ use crate::{
}; };
use bevy_utils::{BoxedFuture, ConditionalSendFuture}; use bevy_utils::{BoxedFuture, ConditionalSendFuture};
use core::marker::PhantomData; use core::marker::PhantomData;
use derive_more::derive::{Display, Error, From};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use thiserror::Error;
/// Asset "processor" logic that reads input asset bytes (stored on [`ProcessContext`]), processes the value in some way, /// Asset "processor" logic that reads input asset bytes (stored on [`ProcessContext`]), processes the value in some way,
/// and then writes the final processed bytes with [`Writer`]. The resulting bytes must be loadable with the given [`Process::OutputLoader`]. /// and then writes the final processed bytes with [`Writer`]. The resulting bytes must be loadable with the given [`Process::OutputLoader`].
@ -126,46 +126,46 @@ pub type LoadAndSaveSettings<LoaderSettings, SaverSettings> =
LoadTransformAndSaveSettings<LoaderSettings, (), SaverSettings>; LoadTransformAndSaveSettings<LoaderSettings, (), SaverSettings>;
/// An error that is encountered during [`Process::process`]. /// An error that is encountered during [`Process::process`].
#[derive(Error, Debug)] #[derive(Error, Display, Debug, From)]
pub enum ProcessError { pub enum ProcessError {
#[error(transparent)] MissingAssetLoaderForExtension(MissingAssetLoaderForExtensionError),
MissingAssetLoaderForExtension(#[from] MissingAssetLoaderForExtensionError), MissingAssetLoaderForTypeName(MissingAssetLoaderForTypeNameError),
#[error(transparent)] #[display("The processor '{_0}' does not exist")]
MissingAssetLoaderForTypeName(#[from] MissingAssetLoaderForTypeNameError), #[error(ignore)]
#[error("The processor '{0}' does not exist")] #[from(ignore)]
MissingProcessor(String), MissingProcessor(String),
#[error("Encountered an AssetReader error for '{path}': {err}")] #[display("Encountered an AssetReader error for '{path}': {err}")]
#[from(ignore)]
AssetReaderError { AssetReaderError {
path: AssetPath<'static>, path: AssetPath<'static>,
err: AssetReaderError, err: AssetReaderError,
}, },
#[error("Encountered an AssetWriter error for '{path}': {err}")] #[display("Encountered an AssetWriter error for '{path}': {err}")]
#[from(ignore)]
AssetWriterError { AssetWriterError {
path: AssetPath<'static>, path: AssetPath<'static>,
err: AssetWriterError, err: AssetWriterError,
}, },
#[error(transparent)] MissingAssetWriterError(MissingAssetWriterError),
MissingAssetWriterError(#[from] MissingAssetWriterError), MissingProcessedAssetReaderError(MissingProcessedAssetReaderError),
#[error(transparent)] MissingProcessedAssetWriterError(MissingProcessedAssetWriterError),
MissingProcessedAssetReaderError(#[from] MissingProcessedAssetReaderError), #[display("Failed to read asset metadata for {path}: {err}")]
#[error(transparent)] #[from(ignore)]
MissingProcessedAssetWriterError(#[from] MissingProcessedAssetWriterError),
#[error("Failed to read asset metadata for {path}: {err}")]
ReadAssetMetaError { ReadAssetMetaError {
path: AssetPath<'static>, path: AssetPath<'static>,
err: AssetReaderError, err: AssetReaderError,
}, },
#[error(transparent)] DeserializeMetaError(DeserializeMetaError),
DeserializeMetaError(#[from] DeserializeMetaError), AssetLoadError(AssetLoadError),
#[error(transparent)] #[display("The wrong meta type was passed into a processor. This is probably an internal implementation error.")]
AssetLoadError(#[from] AssetLoadError),
#[error("The wrong meta type was passed into a processor. This is probably an internal implementation error.")]
WrongMetaType, WrongMetaType,
#[error("Encountered an error while saving the asset: {0}")] #[display("Encountered an error while saving the asset: {_0}")]
AssetSaveError(#[from] Box<dyn core::error::Error + Send + Sync + 'static>), #[from(ignore)]
#[error("Encountered an error while transforming the asset: {0}")] AssetSaveError(Box<dyn core::error::Error + Send + Sync + 'static>),
#[display("Encountered an error while transforming the asset: {_0}")]
#[from(ignore)]
AssetTransformError(Box<dyn core::error::Error + Send + Sync + 'static>), AssetTransformError(Box<dyn core::error::Error + Send + Sync + 'static>),
#[error("Assets without extensions are not supported.")] #[display("Assets without extensions are not supported.")]
ExtensionRequired, ExtensionRequired,
} }

View File

@ -10,8 +10,8 @@ use bevy_tasks::Task;
use bevy_utils::{tracing::warn, Entry, HashMap, HashSet, TypeIdMap}; use bevy_utils::{tracing::warn, Entry, HashMap, HashSet, TypeIdMap};
use core::any::TypeId; use core::any::TypeId;
use crossbeam_channel::Sender; use crossbeam_channel::Sender;
use derive_more::derive::{Display, Error, From};
use either::Either; use either::Either;
use thiserror::Error;
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct AssetInfo { pub(crate) struct AssetInfo {
@ -755,16 +755,16 @@ pub(crate) enum HandleLoadingMode {
Force, Force,
} }
#[derive(Error, Debug)] #[derive(Error, Display, Debug)]
#[error("Cannot allocate a handle because no handle provider exists for asset type {0:?}")] #[display("Cannot allocate a handle because no handle provider exists for asset type {_0:?}")]
#[error(ignore)]
pub struct MissingHandleProviderError(TypeId); pub struct MissingHandleProviderError(TypeId);
/// An error encountered during [`AssetInfos::get_or_create_path_handle_internal`]. /// An error encountered during [`AssetInfos::get_or_create_path_handle_internal`].
#[derive(Error, Debug)] #[derive(Error, Display, Debug, From)]
pub(crate) enum GetOrCreateHandleInternalError { pub(crate) enum GetOrCreateHandleInternalError {
#[error(transparent)] MissingHandleProviderError(MissingHandleProviderError),
MissingHandleProviderError(#[from] MissingHandleProviderError), #[display("Handle does not exist but TypeId was not specified.")]
#[error("Handle does not exist but TypeId was not specified.")]
HandleMissingButTypeIdNotSpecified, HandleMissingButTypeIdNotSpecified,
} }

View File

@ -5,17 +5,14 @@ use crate::{
use alloc::sync::Arc; use alloc::sync::Arc;
use async_broadcast::RecvError; use async_broadcast::RecvError;
use bevy_tasks::IoTaskPool; use bevy_tasks::IoTaskPool;
use bevy_utils::{ use bevy_utils::{tracing::warn, HashMap, TypeIdMap};
tracing::{error, warn},
HashMap, TypeIdMap,
};
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
use bevy_utils::{ use bevy_utils::{
tracing::{info_span, instrument::Instrument}, tracing::{info_span, instrument::Instrument},
ConditionalSendFuture, ConditionalSendFuture,
}; };
use core::any::TypeId; use core::any::TypeId;
use thiserror::Error; use derive_more::derive::{Display, Error, From};
#[derive(Default)] #[derive(Default)]
pub(crate) struct AssetLoaders { pub(crate) struct AssetLoaders {
@ -278,10 +275,9 @@ impl AssetLoaders {
} }
} }
#[derive(Error, Debug, Clone)] #[derive(Error, Display, Debug, Clone, From)]
pub(crate) enum GetLoaderError { pub(crate) enum GetLoaderError {
#[error(transparent)] CouldNotResolve(RecvError),
CouldNotResolve(#[from] RecvError),
} }
#[derive(Clone)] #[derive(Clone)]

View File

@ -31,13 +31,13 @@ use core::{
panic::AssertUnwindSafe, panic::AssertUnwindSafe,
}; };
use crossbeam_channel::{Receiver, Sender}; use crossbeam_channel::{Receiver, Sender};
use derive_more::derive::{Display, Error, From};
use either::Either; use either::Either;
use futures_lite::{FutureExt, StreamExt}; use futures_lite::{FutureExt, StreamExt};
use info::*; use info::*;
use loaders::*; use loaders::*;
use parking_lot::RwLock; use parking_lot::RwLock;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use thiserror::Error;
/// Loads and tracks the state of [`Asset`] values from a configured [`AssetReader`](crate::io::AssetReader). This can be used to kick off new asset loads and /// Loads and tracks the state of [`Asset`] values from a configured [`AssetReader`](crate::io::AssetReader). This can be used to kick off new asset loads and
/// retrieve their current load states. /// retrieve their current load states.
@ -1532,55 +1532,53 @@ pub enum RecursiveDependencyLoadState {
} }
/// An error that occurs during an [`Asset`] load. /// An error that occurs during an [`Asset`] load.
#[derive(Error, Debug, Clone, PartialEq, Eq)] #[derive(Error, Display, Debug, Clone, PartialEq, Eq, From)]
pub enum AssetLoadError { pub enum AssetLoadError {
#[error("Requested handle of type {requested:?} for asset '{path}' does not match actual asset type '{actual_asset_name}', which used loader '{loader_name}'")] #[display("Requested handle of type {requested:?} for asset '{path}' does not match actual asset type '{actual_asset_name}', which used loader '{loader_name}'")]
RequestedHandleTypeMismatch { RequestedHandleTypeMismatch {
path: AssetPath<'static>, path: AssetPath<'static>,
requested: TypeId, requested: TypeId,
actual_asset_name: &'static str, actual_asset_name: &'static str,
loader_name: &'static str, loader_name: &'static str,
}, },
#[error("Could not find an asset loader matching: Loader Name: {loader_name:?}; Asset Type: {loader_name:?}; Extension: {extension:?}; Path: {asset_path:?};")] #[display("Could not find an asset loader matching: Loader Name: {loader_name:?}; Asset Type: {loader_name:?}; Extension: {extension:?}; Path: {asset_path:?};")]
MissingAssetLoader { MissingAssetLoader {
loader_name: Option<String>, loader_name: Option<String>,
asset_type_id: Option<TypeId>, asset_type_id: Option<TypeId>,
extension: Option<String>, extension: Option<String>,
asset_path: Option<String>, asset_path: Option<String>,
}, },
#[error(transparent)] MissingAssetLoaderForExtension(MissingAssetLoaderForExtensionError),
MissingAssetLoaderForExtension(#[from] MissingAssetLoaderForExtensionError), MissingAssetLoaderForTypeName(MissingAssetLoaderForTypeNameError),
#[error(transparent)] MissingAssetLoaderForTypeIdError(MissingAssetLoaderForTypeIdError),
MissingAssetLoaderForTypeName(#[from] MissingAssetLoaderForTypeNameError), AssetReaderError(AssetReaderError),
#[error(transparent)] MissingAssetSourceError(MissingAssetSourceError),
MissingAssetLoaderForTypeIdError(#[from] MissingAssetLoaderForTypeIdError), MissingProcessedAssetReaderError(MissingProcessedAssetReaderError),
#[error(transparent)] #[display("Encountered an error while reading asset metadata bytes")]
AssetReaderError(#[from] AssetReaderError),
#[error(transparent)]
MissingAssetSourceError(#[from] MissingAssetSourceError),
#[error(transparent)]
MissingProcessedAssetReaderError(#[from] MissingProcessedAssetReaderError),
#[error("Encountered an error while reading asset metadata bytes")]
AssetMetaReadError, AssetMetaReadError,
#[error("Failed to deserialize meta for asset {path}: {error}")] #[display("Failed to deserialize meta for asset {path}: {error}")]
DeserializeMeta { DeserializeMeta {
path: AssetPath<'static>, path: AssetPath<'static>,
error: Box<DeserializeMetaError>, error: Box<DeserializeMetaError>,
}, },
#[error("Asset '{path}' is configured to be processed. It cannot be loaded directly.")] #[display("Asset '{path}' is configured to be processed. It cannot be loaded directly.")]
CannotLoadProcessedAsset { path: AssetPath<'static> }, #[from(ignore)]
#[error("Asset '{path}' is configured to be ignored. It cannot be loaded.")] CannotLoadProcessedAsset {
CannotLoadIgnoredAsset { path: AssetPath<'static> }, path: AssetPath<'static>,
#[error("Failed to load asset '{path}', asset loader '{loader_name}' panicked")] },
#[display("Asset '{path}' is configured to be ignored. It cannot be loaded.")]
#[from(ignore)]
CannotLoadIgnoredAsset {
path: AssetPath<'static>,
},
#[display("Failed to load asset '{path}', asset loader '{loader_name}' panicked")]
AssetLoaderPanic { AssetLoaderPanic {
path: AssetPath<'static>, path: AssetPath<'static>,
loader_name: &'static str, loader_name: &'static str,
}, },
#[error(transparent)] AssetLoaderError(AssetLoaderError),
AssetLoaderError(#[from] AssetLoaderError), AddAsyncError(AddAsyncError),
#[error(transparent)] #[display("The file at '{}' does not contain the labeled asset '{}'; it contains the following {} assets: {}",
AddAsyncError(#[from] AddAsyncError),
#[error("The file at '{}' does not contain the labeled asset '{}'; it contains the following {} assets: {}",
base_path, base_path,
label, label,
all_labels.len(), all_labels.len(),
@ -1592,8 +1590,8 @@ pub enum AssetLoadError {
}, },
} }
#[derive(Error, Debug, Clone)] #[derive(Error, Display, Debug, Clone)]
#[error("Failed to load asset '{path}' with asset loader '{loader_name}': {error}")] #[display("Failed to load asset '{path}' with asset loader '{loader_name}': {error}")]
pub struct AssetLoaderError { pub struct AssetLoaderError {
path: AssetPath<'static>, path: AssetPath<'static>,
loader_name: &'static str, loader_name: &'static str,
@ -1618,8 +1616,8 @@ impl AssetLoaderError {
} }
} }
#[derive(Error, Debug, Clone)] #[derive(Error, Display, Debug, Clone)]
#[error("An error occurred while resolving an asset added by `add_async`: {error}")] #[display("An error occurred while resolving an asset added by `add_async`: {error}")]
pub struct AddAsyncError { pub struct AddAsyncError {
error: Arc<dyn core::error::Error + Send + Sync + 'static>, error: Arc<dyn core::error::Error + Send + Sync + 'static>,
} }
@ -1635,22 +1633,22 @@ impl PartialEq for AddAsyncError {
impl Eq for AddAsyncError {} impl Eq for AddAsyncError {}
/// An error that occurs when an [`AssetLoader`] is not registered for a given extension. /// An error that occurs when an [`AssetLoader`] is not registered for a given extension.
#[derive(Error, Debug, Clone, PartialEq, Eq)] #[derive(Error, Display, Debug, Clone, PartialEq, Eq)]
#[error("no `AssetLoader` found{}", format_missing_asset_ext(.extensions))] #[display("no `AssetLoader` found{}", format_missing_asset_ext(extensions))]
pub struct MissingAssetLoaderForExtensionError { pub struct MissingAssetLoaderForExtensionError {
extensions: Vec<String>, extensions: Vec<String>,
} }
/// An error that occurs when an [`AssetLoader`] is not registered for a given [`std::any::type_name`]. /// An error that occurs when an [`AssetLoader`] is not registered for a given [`std::any::type_name`].
#[derive(Error, Debug, Clone, PartialEq, Eq)] #[derive(Error, Display, Debug, Clone, PartialEq, Eq)]
#[error("no `AssetLoader` found with the name '{type_name}'")] #[display("no `AssetLoader` found with the name '{type_name}'")]
pub struct MissingAssetLoaderForTypeNameError { pub struct MissingAssetLoaderForTypeNameError {
type_name: String, type_name: String,
} }
/// An error that occurs when an [`AssetLoader`] is not registered for a given [`Asset`] [`TypeId`]. /// An error that occurs when an [`AssetLoader`] is not registered for a given [`Asset`] [`TypeId`].
#[derive(Error, Debug, Clone, PartialEq, Eq)] #[derive(Error, Display, Debug, Clone, PartialEq, Eq)]
#[error("no `AssetLoader` found with the ID '{type_id:?}'")] #[display("no `AssetLoader` found with the ID '{type_id:?}'")]
pub struct MissingAssetLoaderForTypeIdError { pub struct MissingAssetLoaderForTypeIdError {
pub type_id: TypeId, pub type_id: TypeId,
} }