mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
Optimize common usages of AssetReader
(#14082)
# Objective The `AssetReader` trait allows customizing the behavior of fetching bytes for an `AssetPath`, and expects implementors to return `dyn AsyncRead + AsyncSeek`. This gives implementors of `AssetLoader` great flexibility to tightly integrate their asset loading behavior with the asynchronous task system. However, almost all implementors of `AssetLoader` don't use the async functionality at all, and just call `AsyncReadExt::read_to_end(&mut Vec<u8>)`. This is incredibly inefficient, as this method repeatedly calls `poll_read` on the trait object, filling the vector 32 bytes at a time. At my work we have assets that are hundreds of megabytes which makes this a meaningful overhead. ## Solution Turn the `Reader` type alias into an actual trait, with a provided method `read_to_end`. This provided method should be more efficient than the existing extension method, as the compiler will know the underlying type of `Reader` when generating this function, which removes the repeated dynamic dispatches and allows the compiler to make further optimizations after inlining. Individual implementors are able to override the provided implementation -- for simple asset readers that just copy bytes from one buffer to another, this allows removing a large amount of overhead from the provided implementation. Now that `Reader` is an actual trait, I also improved the ergonomics for implementing `AssetReader`. Currently, implementors are expected to box their reader and return it as a trait object, which adds unnecessary boilerplate to implementations. This PR changes that trait method to return a pseudo trait alias, which allows implementors to return `impl Reader` instead of `Box<dyn Reader>`. Now, the boilerplate for boxing occurs in `ErasedAssetReader`. ## Testing I made identical changes to my company's fork of bevy. Our app, which makes heavy use of `read_to_end` for asset loading, still worked properly after this. I am not aware if we have a more systematic way of testing asset loading for correctness. --- ## Migration Guide The trait method `bevy_asset::io::AssetReader::read` (and `read_meta`) now return an opaque type instead of a boxed trait object. Implementors of these methods should change the type signatures appropriately ```rust impl AssetReader for MyReader { // Before async fn read<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> { let reader = // construct a reader Box::new(reader) as Box<Reader<'a>> } // After async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> { // create a reader } } ``` `bevy::asset::io::Reader` is now a trait, rather than a type alias for a trait object. Implementors of `AssetLoader::load` will need to adjust the method signature accordingly ```rust impl AssetLoader for MyLoader { async fn load<'a>( &'a self, // Before: reader: &'a mut bevy::asset::io::Reader, // After: reader: &'a mut dyn bevy::asset::io::Reader, _: &'a Self::Settings, load_context: &'a mut LoadContext<'_>, ) -> Result<Self::Asset, Self::Error> { } ``` Additionally, implementors of `AssetReader` that return a type implementing `futures_io::AsyncRead` and `AsyncSeek` might need to explicitly implement `bevy::asset::io::Reader` for that type. ```rust impl bevy::asset::io::Reader for MyAsyncReadAndSeek {} ```
This commit is contained in:
parent
bd7dcd3f6d
commit
5876352206
29 changed files with 260 additions and 149 deletions
|
@ -4,7 +4,7 @@ use std::io::{self, Write};
|
|||
use std::ops::{Index, IndexMut};
|
||||
|
||||
use bevy_asset::io::Reader;
|
||||
use bevy_asset::{Asset, AssetId, AssetLoader, AssetPath, AsyncReadExt as _, Handle, LoadContext};
|
||||
use bevy_asset::{Asset, AssetId, AssetLoader, AssetPath, Handle, LoadContext};
|
||||
use bevy_reflect::{Reflect, ReflectSerialize};
|
||||
use petgraph::graph::{DiGraph, NodeIndex};
|
||||
use ron::de::SpannedError;
|
||||
|
@ -337,7 +337,7 @@ impl AssetLoader for AnimationGraphAssetLoader {
|
|||
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
_: &'a Self::Settings,
|
||||
load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Self::Asset, Self::Error> {
|
||||
|
|
|
@ -28,6 +28,7 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev", features = [
|
|||
bevy_tasks = { path = "../bevy_tasks", version = "0.14.0-dev" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.14.0-dev" }
|
||||
|
||||
stackfuture = "0.3"
|
||||
async-broadcast = "0.5"
|
||||
async-fs = "2.0"
|
||||
async-lock = "3.0"
|
||||
|
|
|
@ -16,7 +16,7 @@ use std::{ffi::CString, path::Path};
|
|||
pub struct AndroidAssetReader;
|
||||
|
||||
impl AssetReader for AndroidAssetReader {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
let asset_manager = bevy_winit::ANDROID_APP
|
||||
.get()
|
||||
.expect("Bevy must be setup with the #[bevy_main] macro on Android")
|
||||
|
@ -25,11 +25,11 @@ impl AssetReader for AndroidAssetReader {
|
|||
.open(&CString::new(path.to_str().unwrap()).unwrap())
|
||||
.ok_or(AssetReaderError::NotFound(path.to_path_buf()))?;
|
||||
let bytes = opened_asset.buffer()?;
|
||||
let reader: Box<Reader> = Box::new(VecReader::new(bytes.to_vec()));
|
||||
let reader = VecReader::new(bytes.to_vec());
|
||||
Ok(reader)
|
||||
}
|
||||
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
let meta_path = get_meta_path(path);
|
||||
let asset_manager = bevy_winit::ANDROID_APP
|
||||
.get()
|
||||
|
@ -39,7 +39,7 @@ impl AssetReader for AndroidAssetReader {
|
|||
.open(&CString::new(meta_path.to_str().unwrap()).unwrap())
|
||||
.ok_or(AssetReaderError::NotFound(meta_path))?;
|
||||
let bytes = opened_asset.buffer()?;
|
||||
let reader: Box<Reader> = Box::new(VecReader::new(bytes.to_vec()));
|
||||
let reader = VecReader::new(bytes.to_vec());
|
||||
Ok(reader)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,40 +9,30 @@ use std::path::Path;
|
|||
|
||||
use super::{FileAssetReader, FileAssetWriter};
|
||||
|
||||
impl Reader for File {}
|
||||
|
||||
impl AssetReader for FileAssetReader {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
let full_path = self.root_path.join(path);
|
||||
match File::open(&full_path).await {
|
||||
Ok(file) => {
|
||||
let reader: Box<Reader> = Box::new(file);
|
||||
Ok(reader)
|
||||
File::open(&full_path).await.map_err(|e| {
|
||||
if e.kind() == std::io::ErrorKind::NotFound {
|
||||
AssetReaderError::NotFound(full_path)
|
||||
} else {
|
||||
e.into()
|
||||
}
|
||||
Err(e) => {
|
||||
if e.kind() == std::io::ErrorKind::NotFound {
|
||||
Err(AssetReaderError::NotFound(full_path))
|
||||
} else {
|
||||
Err(e.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
let meta_path = get_meta_path(path);
|
||||
let full_path = self.root_path.join(meta_path);
|
||||
match File::open(&full_path).await {
|
||||
Ok(file) => {
|
||||
let reader: Box<Reader> = Box::new(file);
|
||||
Ok(reader)
|
||||
File::open(&full_path).await.map_err(|e| {
|
||||
if e.kind() == std::io::ErrorKind::NotFound {
|
||||
AssetReaderError::NotFound(full_path)
|
||||
} else {
|
||||
e.into()
|
||||
}
|
||||
Err(e) => {
|
||||
if e.kind() == std::io::ErrorKind::NotFound {
|
||||
Err(AssetReaderError::NotFound(full_path))
|
||||
} else {
|
||||
Err(e.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn read_directory<'a>(
|
||||
|
|
|
@ -42,6 +42,16 @@ impl AsyncSeek for FileReader {
|
|||
}
|
||||
}
|
||||
|
||||
impl Reader for FileReader {
|
||||
fn read_to_end<'a>(
|
||||
&'a mut self,
|
||||
buf: &'a mut Vec<u8>,
|
||||
) -> stackfuture::StackFuture<'a, std::io::Result<usize>, { crate::io::STACK_FUTURE_SIZE }>
|
||||
{
|
||||
stackfuture::StackFuture::from(async { self.0.read_to_end(buf) })
|
||||
}
|
||||
}
|
||||
|
||||
struct FileWriter(File);
|
||||
|
||||
impl AsyncWrite for FileWriter {
|
||||
|
@ -87,13 +97,10 @@ impl Stream for DirReader {
|
|||
}
|
||||
|
||||
impl AssetReader for FileAssetReader {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
let full_path = self.root_path.join(path);
|
||||
match File::open(&full_path) {
|
||||
Ok(file) => {
|
||||
let reader: Box<Reader> = Box::new(FileReader(file));
|
||||
Ok(reader)
|
||||
}
|
||||
Ok(file) => Ok(FileReader(file)),
|
||||
Err(e) => {
|
||||
if e.kind() == std::io::ErrorKind::NotFound {
|
||||
Err(AssetReaderError::NotFound(full_path))
|
||||
|
@ -104,14 +111,11 @@ impl AssetReader for FileAssetReader {
|
|||
}
|
||||
}
|
||||
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
let meta_path = get_meta_path(path);
|
||||
let full_path = self.root_path.join(meta_path);
|
||||
match File::open(&full_path) {
|
||||
Ok(file) => {
|
||||
let reader: Box<Reader> = Box::new(FileReader(file));
|
||||
Ok(reader)
|
||||
}
|
||||
Ok(file) => Ok(FileReader(file)),
|
||||
Err(e) => {
|
||||
if e.kind() == std::io::ErrorKind::NotFound {
|
||||
Err(AssetReaderError::NotFound(full_path))
|
||||
|
|
|
@ -55,7 +55,7 @@ impl<R: AssetReader> GatedReader<R> {
|
|||
}
|
||||
|
||||
impl<R: AssetReader> AssetReader for GatedReader<R> {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
let receiver = {
|
||||
let mut gates = self.gates.write();
|
||||
let gates = gates
|
||||
|
@ -68,7 +68,7 @@ impl<R: AssetReader> AssetReader for GatedReader<R> {
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
self.reader.read_meta(path).await
|
||||
}
|
||||
|
||||
|
|
|
@ -277,29 +277,41 @@ impl AsyncSeek for DataReader {
|
|||
}
|
||||
}
|
||||
|
||||
impl Reader for DataReader {
|
||||
fn read_to_end<'a>(
|
||||
&'a mut self,
|
||||
buf: &'a mut Vec<u8>,
|
||||
) -> stackfuture::StackFuture<'a, std::io::Result<usize>, { super::STACK_FUTURE_SIZE }> {
|
||||
stackfuture::StackFuture::from(async {
|
||||
if self.bytes_read >= self.data.value().len() {
|
||||
Ok(0)
|
||||
} else {
|
||||
buf.extend_from_slice(&self.data.value()[self.bytes_read..]);
|
||||
let n = self.data.value().len() - self.bytes_read;
|
||||
self.bytes_read = self.data.value().len();
|
||||
Ok(n)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AssetReader for MemoryAssetReader {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
self.root
|
||||
.get_asset(path)
|
||||
.map(|data| {
|
||||
let reader: Box<Reader> = Box::new(DataReader {
|
||||
data,
|
||||
bytes_read: 0,
|
||||
});
|
||||
reader
|
||||
.map(|data| DataReader {
|
||||
data,
|
||||
bytes_read: 0,
|
||||
})
|
||||
.ok_or_else(|| AssetReaderError::NotFound(path.to_path_buf()))
|
||||
}
|
||||
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
self.root
|
||||
.get_metadata(path)
|
||||
.map(|data| {
|
||||
let reader: Box<Reader> = Box::new(DataReader {
|
||||
data,
|
||||
bytes_read: 0,
|
||||
});
|
||||
reader
|
||||
.map(|data| DataReader {
|
||||
data,
|
||||
bytes_read: 0,
|
||||
})
|
||||
.ok_or_else(|| AssetReaderError::NotFound(path.to_path_buf()))
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ pub mod wasm;
|
|||
|
||||
mod source;
|
||||
|
||||
pub use futures_lite::{AsyncReadExt, AsyncWriteExt};
|
||||
pub use futures_lite::AsyncWriteExt;
|
||||
pub use source::*;
|
||||
|
||||
use bevy_utils::{BoxedFuture, ConditionalSendFuture};
|
||||
|
@ -72,11 +72,59 @@ impl From<std::io::Error> for AssetReaderError {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait AsyncReadAndSeek: AsyncRead + AsyncSeek {}
|
||||
/// The maximum size of a future returned from [`Reader::read_to_end`].
|
||||
/// This is large enough to fit ten references.
|
||||
// Ideally this would be even smaller (ReadToEndFuture only needs space for two references based on its definition),
|
||||
// but compiler optimizations can apparently inflate the stack size of futures due to inlining, which makes
|
||||
// a higher maximum necessary.
|
||||
pub const STACK_FUTURE_SIZE: usize = 10 * std::mem::size_of::<&()>();
|
||||
|
||||
impl<T: AsyncRead + AsyncSeek> AsyncReadAndSeek for T {}
|
||||
pub use stackfuture::StackFuture;
|
||||
|
||||
pub type Reader<'a> = dyn AsyncReadAndSeek + Unpin + Send + Sync + 'a;
|
||||
/// A type returned from [`AssetReader::read`], which is used to read the contents of a file
|
||||
/// (or virtual file) corresponding to an asset.
|
||||
///
|
||||
/// This is essentially a trait alias for types implementing [`AsyncRead`] and [`AsyncSeek`].
|
||||
/// The only reason a blanket implementation is not provided for applicable types is to allow
|
||||
/// implementors to override the provided implementation of [`Reader::read_to_end`].
|
||||
pub trait Reader: AsyncRead + AsyncSeek + Unpin + Send + Sync {
|
||||
/// Reads the entire contents of this reader and appends them to a vec.
|
||||
///
|
||||
/// # Note for implementors
|
||||
/// You should override the provided implementation if you can fill up the buffer more
|
||||
/// efficiently than the default implementation, which calls `poll_read` repeatedly to
|
||||
/// fill up the buffer 32 bytes at a time.
|
||||
fn read_to_end<'a>(
|
||||
&'a mut self,
|
||||
buf: &'a mut Vec<u8>,
|
||||
) -> StackFuture<'a, std::io::Result<usize>, STACK_FUTURE_SIZE> {
|
||||
let future = futures_lite::AsyncReadExt::read_to_end(self, buf);
|
||||
StackFuture::from(future)
|
||||
}
|
||||
}
|
||||
|
||||
impl Reader for Box<dyn Reader + '_> {
|
||||
fn read_to_end<'a>(
|
||||
&'a mut self,
|
||||
buf: &'a mut Vec<u8>,
|
||||
) -> StackFuture<'a, std::io::Result<usize>, STACK_FUTURE_SIZE> {
|
||||
(**self).read_to_end(buf)
|
||||
}
|
||||
}
|
||||
|
||||
/// A future that returns a value or an [`AssetReaderError`]
|
||||
pub trait AssetReaderFuture:
|
||||
ConditionalSendFuture<Output = Result<Self::Value, AssetReaderError>>
|
||||
{
|
||||
type Value;
|
||||
}
|
||||
|
||||
impl<F, T> AssetReaderFuture for F
|
||||
where
|
||||
F: ConditionalSendFuture<Output = Result<T, AssetReaderError>>,
|
||||
{
|
||||
type Value = T;
|
||||
}
|
||||
|
||||
/// Performs read operations on an asset storage. [`AssetReader`] exposes a "virtual filesystem"
|
||||
/// API, where asset bytes and asset metadata bytes are both stored and accessible for a given
|
||||
|
@ -85,15 +133,29 @@ pub type Reader<'a> = dyn AsyncReadAndSeek + Unpin + Send + Sync + 'a;
|
|||
/// Also see [`AssetWriter`].
|
||||
pub trait AssetReader: Send + Sync + 'static {
|
||||
/// Returns a future to load the full file data at the provided path.
|
||||
fn read<'a>(
|
||||
&'a self,
|
||||
path: &'a Path,
|
||||
) -> impl ConditionalSendFuture<Output = Result<Box<Reader<'a>>, AssetReaderError>>;
|
||||
///
|
||||
/// # Note for implementors
|
||||
/// The preferred style for implementing this method is an `async fn` returning an opaque type.
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use std::path::Path;
|
||||
/// # use bevy_asset::{prelude::*, io::{AssetReader, PathStream, Reader, AssetReaderError}};
|
||||
/// # struct MyReader;
|
||||
/// impl AssetReader for MyReader {
|
||||
/// async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
/// // ...
|
||||
/// # let val: Box<dyn Reader> = unimplemented!(); Ok(val)
|
||||
/// }
|
||||
/// # async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
/// # let val: Box<dyn Reader> = unimplemented!(); Ok(val) }
|
||||
/// # async fn read_directory<'a>(&'a self, path: &'a Path) -> Result<Box<PathStream>, AssetReaderError> { unimplemented!() }
|
||||
/// # async fn is_directory<'a>(&'a self, path: &'a Path) -> Result<bool, AssetReaderError> { unimplemented!() }
|
||||
/// # async fn read_meta_bytes<'a>(&'a self, path: &'a Path) -> Result<Vec<u8>, AssetReaderError> { unimplemented!() }
|
||||
/// }
|
||||
/// ```
|
||||
fn read<'a>(&'a self, path: &'a Path) -> impl AssetReaderFuture<Value: Reader + 'a>;
|
||||
/// Returns a future to load the full file data at the provided path.
|
||||
fn read_meta<'a>(
|
||||
&'a self,
|
||||
path: &'a Path,
|
||||
) -> impl ConditionalSendFuture<Output = Result<Box<Reader<'a>>, AssetReaderError>>;
|
||||
fn read_meta<'a>(&'a self, path: &'a Path) -> impl AssetReaderFuture<Value: Reader + 'a>;
|
||||
/// Returns an iterator of directory entry names at the provided path.
|
||||
fn read_directory<'a>(
|
||||
&'a self,
|
||||
|
@ -123,13 +185,15 @@ pub trait AssetReader: Send + Sync + 'static {
|
|||
/// as [`AssetReader`] isn't currently object safe.
|
||||
pub trait ErasedAssetReader: Send + Sync + 'static {
|
||||
/// Returns a future to load the full file data at the provided path.
|
||||
fn read<'a>(&'a self, path: &'a Path)
|
||||
-> BoxedFuture<Result<Box<Reader<'a>>, AssetReaderError>>;
|
||||
fn read<'a>(
|
||||
&'a self,
|
||||
path: &'a Path,
|
||||
) -> BoxedFuture<Result<Box<dyn Reader + 'a>, AssetReaderError>>;
|
||||
/// Returns a future to load the full file data at the provided path.
|
||||
fn read_meta<'a>(
|
||||
&'a self,
|
||||
path: &'a Path,
|
||||
) -> BoxedFuture<Result<Box<Reader<'a>>, AssetReaderError>>;
|
||||
) -> BoxedFuture<Result<Box<dyn Reader + 'a>, AssetReaderError>>;
|
||||
/// Returns an iterator of directory entry names at the provided path.
|
||||
fn read_directory<'a>(
|
||||
&'a self,
|
||||
|
@ -149,14 +213,20 @@ impl<T: AssetReader> ErasedAssetReader for T {
|
|||
fn read<'a>(
|
||||
&'a self,
|
||||
path: &'a Path,
|
||||
) -> BoxedFuture<Result<Box<Reader<'a>>, AssetReaderError>> {
|
||||
Box::pin(Self::read(self, path))
|
||||
) -> BoxedFuture<Result<Box<dyn Reader + 'a>, AssetReaderError>> {
|
||||
Box::pin(async {
|
||||
let reader = Self::read(self, path).await?;
|
||||
Ok(Box::new(reader) as Box<dyn Reader>)
|
||||
})
|
||||
}
|
||||
fn read_meta<'a>(
|
||||
&'a self,
|
||||
path: &'a Path,
|
||||
) -> BoxedFuture<Result<Box<Reader<'a>>, AssetReaderError>> {
|
||||
Box::pin(Self::read_meta(self, path))
|
||||
) -> BoxedFuture<Result<Box<dyn Reader + 'a>, AssetReaderError>> {
|
||||
Box::pin(async {
|
||||
let reader = Self::read_meta(self, path).await?;
|
||||
Ok(Box::new(reader) as Box<dyn Reader>)
|
||||
})
|
||||
}
|
||||
fn read_directory<'a>(
|
||||
&'a self,
|
||||
|
@ -498,6 +568,24 @@ impl AsyncSeek for VecReader {
|
|||
}
|
||||
}
|
||||
|
||||
impl Reader for VecReader {
|
||||
fn read_to_end<'a>(
|
||||
&'a mut self,
|
||||
buf: &'a mut Vec<u8>,
|
||||
) -> StackFuture<'a, std::io::Result<usize>, STACK_FUTURE_SIZE> {
|
||||
StackFuture::from(async {
|
||||
if self.bytes_read >= self.bytes.len() {
|
||||
Ok(0)
|
||||
} else {
|
||||
buf.extend_from_slice(&self.bytes[self.bytes_read..]);
|
||||
let n = self.bytes.len() - self.bytes_read;
|
||||
self.bytes_read = self.bytes.len();
|
||||
Ok(n)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// An [`AsyncRead`] implementation capable of reading a [`&[u8]`].
|
||||
pub struct SliceReader<'a> {
|
||||
bytes: &'a [u8],
|
||||
|
@ -565,6 +653,24 @@ impl<'a> AsyncSeek for SliceReader<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Reader for SliceReader<'_> {
|
||||
fn read_to_end<'a>(
|
||||
&'a mut self,
|
||||
buf: &'a mut Vec<u8>,
|
||||
) -> StackFuture<'a, std::io::Result<usize>, STACK_FUTURE_SIZE> {
|
||||
StackFuture::from(async {
|
||||
if self.bytes_read >= self.bytes.len() {
|
||||
Ok(0)
|
||||
} else {
|
||||
buf.extend_from_slice(&self.bytes[self.bytes_read..]);
|
||||
let n = self.bytes.len() - self.bytes_read;
|
||||
self.bytes_read = self.bytes.len();
|
||||
Ok(n)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends `.meta` to the given path.
|
||||
pub(crate) fn get_meta_path(path: &Path) -> PathBuf {
|
||||
let mut meta_path = path.to_path_buf();
|
||||
|
|
|
@ -51,7 +51,7 @@ impl ProcessorGatedReader {
|
|||
}
|
||||
|
||||
impl AssetReader for ProcessorGatedReader {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
let asset_path = AssetPath::from(path.to_path_buf()).with_source(self.source.clone());
|
||||
trace!("Waiting for processing to finish before reading {asset_path}");
|
||||
let process_result = self
|
||||
|
@ -67,11 +67,11 @@ impl AssetReader for ProcessorGatedReader {
|
|||
trace!("Processing finished with {asset_path}, reading {process_result:?}",);
|
||||
let lock = self.get_transaction_lock(&asset_path).await?;
|
||||
let asset_reader = self.reader.read(path).await?;
|
||||
let reader: Box<Reader<'a>> = Box::new(TransactionLockedReader::new(asset_reader, lock));
|
||||
let reader = TransactionLockedReader::new(asset_reader, lock);
|
||||
Ok(reader)
|
||||
}
|
||||
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
let asset_path = AssetPath::from(path.to_path_buf()).with_source(self.source.clone());
|
||||
trace!("Waiting for processing to finish before reading meta for {asset_path}",);
|
||||
let process_result = self
|
||||
|
@ -87,7 +87,7 @@ impl AssetReader for ProcessorGatedReader {
|
|||
trace!("Processing finished with {process_result:?}, reading meta for {asset_path}",);
|
||||
let lock = self.get_transaction_lock(&asset_path).await?;
|
||||
let meta_reader = self.reader.read_meta(path).await?;
|
||||
let reader: Box<Reader<'a>> = Box::new(TransactionLockedReader::new(meta_reader, lock));
|
||||
let reader = TransactionLockedReader::new(meta_reader, lock);
|
||||
Ok(reader)
|
||||
}
|
||||
|
||||
|
@ -119,12 +119,12 @@ impl AssetReader for ProcessorGatedReader {
|
|||
|
||||
/// An [`AsyncRead`] impl that will hold its asset's transaction lock until [`TransactionLockedReader`] is dropped.
|
||||
pub struct TransactionLockedReader<'a> {
|
||||
reader: Box<Reader<'a>>,
|
||||
reader: Box<dyn Reader + 'a>,
|
||||
_file_transaction_lock: RwLockReadGuardArc<()>,
|
||||
}
|
||||
|
||||
impl<'a> TransactionLockedReader<'a> {
|
||||
fn new(reader: Box<Reader<'a>>, file_transaction_lock: RwLockReadGuardArc<()>) -> Self {
|
||||
fn new(reader: Box<dyn Reader + 'a>, file_transaction_lock: RwLockReadGuardArc<()>) -> Self {
|
||||
Self {
|
||||
reader,
|
||||
_file_transaction_lock: file_transaction_lock,
|
||||
|
@ -132,7 +132,7 @@ impl<'a> TransactionLockedReader<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> AsyncRead for TransactionLockedReader<'a> {
|
||||
impl AsyncRead for TransactionLockedReader<'_> {
|
||||
fn poll_read(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut std::task::Context<'_>,
|
||||
|
@ -142,7 +142,7 @@ impl<'a> AsyncRead for TransactionLockedReader<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> AsyncSeek for TransactionLockedReader<'a> {
|
||||
impl AsyncSeek for TransactionLockedReader<'_> {
|
||||
fn poll_seek(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut std::task::Context<'_>,
|
||||
|
@ -151,3 +151,12 @@ impl<'a> AsyncSeek for TransactionLockedReader<'a> {
|
|||
Pin::new(&mut self.reader).poll_seek(cx, pos)
|
||||
}
|
||||
}
|
||||
|
||||
impl Reader for TransactionLockedReader<'_> {
|
||||
fn read_to_end<'a>(
|
||||
&'a mut self,
|
||||
buf: &'a mut Vec<u8>,
|
||||
) -> stackfuture::StackFuture<'a, std::io::Result<usize>, { super::STACK_FUTURE_SIZE }> {
|
||||
self.reader.read_to_end(buf)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ fn js_value_to_err(context: &str) -> impl FnOnce(JsValue) -> std::io::Error + '_
|
|||
}
|
||||
|
||||
impl HttpWasmAssetReader {
|
||||
async fn fetch_bytes<'a>(&self, path: PathBuf) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn fetch_bytes<'a>(&self, path: PathBuf) -> Result<impl Reader, AssetReaderError> {
|
||||
// The JS global scope includes a self-reference via a specialising name, which can be used to determine the type of global context available.
|
||||
let global: Global = js_sys::global().unchecked_into();
|
||||
let promise = if !global.window().is_undefined() {
|
||||
|
@ -77,7 +77,7 @@ impl HttpWasmAssetReader {
|
|||
200 => {
|
||||
let data = JsFuture::from(resp.array_buffer().unwrap()).await.unwrap();
|
||||
let bytes = Uint8Array::new(&data).to_vec();
|
||||
let reader: Box<Reader> = Box::new(VecReader::new(bytes));
|
||||
let reader = VecReader::new(bytes);
|
||||
Ok(reader)
|
||||
}
|
||||
404 => Err(AssetReaderError::NotFound(path)),
|
||||
|
@ -87,12 +87,12 @@ impl HttpWasmAssetReader {
|
|||
}
|
||||
|
||||
impl AssetReader for HttpWasmAssetReader {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
let path = self.root_path.join(path);
|
||||
self.fetch_bytes(path).await
|
||||
}
|
||||
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
let meta_path = get_meta_path(&self.root_path.join(path));
|
||||
self.fetch_bytes(meta_path).await
|
||||
}
|
||||
|
|
|
@ -460,7 +460,6 @@ mod tests {
|
|||
use bevy_log::LogPlugin;
|
||||
use bevy_reflect::TypePath;
|
||||
use bevy_utils::{Duration, HashMap};
|
||||
use futures_lite::AsyncReadExt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{path::Path, sync::Arc};
|
||||
use thiserror::Error;
|
||||
|
@ -510,7 +509,7 @@ mod tests {
|
|||
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
_settings: &'a Self::Settings,
|
||||
load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Self::Asset, Self::Error> {
|
||||
|
@ -584,13 +583,13 @@ mod tests {
|
|||
async fn read_meta<'a>(
|
||||
&'a self,
|
||||
path: &'a Path,
|
||||
) -> Result<Box<bevy_asset::io::Reader<'a>>, AssetReaderError> {
|
||||
) -> Result<impl bevy_asset::io::Reader + 'a, AssetReaderError> {
|
||||
self.memory_reader.read_meta(path).await
|
||||
}
|
||||
async fn read<'a>(
|
||||
&'a self,
|
||||
path: &'a Path,
|
||||
) -> Result<Box<bevy_asset::io::Reader<'a>>, bevy_asset::io::AssetReaderError> {
|
||||
) -> Result<impl bevy_asset::io::Reader + 'a, bevy_asset::io::AssetReaderError> {
|
||||
let attempt_number = {
|
||||
let mut attempt_counters = self.attempt_counters.lock().unwrap();
|
||||
if let Some(existing) = attempt_counters.get_mut(path) {
|
||||
|
|
|
@ -9,7 +9,6 @@ use crate::{
|
|||
use bevy_ecs::world::World;
|
||||
use bevy_utils::{BoxedFuture, ConditionalSendFuture, CowArc, HashMap, HashSet};
|
||||
use downcast_rs::{impl_downcast, Downcast};
|
||||
use futures_lite::AsyncReadExt;
|
||||
use ron::error::SpannedError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
|
@ -30,7 +29,7 @@ pub trait AssetLoader: 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,
|
||||
reader: &'a mut dyn Reader,
|
||||
settings: &'a Self::Settings,
|
||||
load_context: &'a mut LoadContext,
|
||||
) -> impl ConditionalSendFuture<Output = Result<Self::Asset, Self::Error>>;
|
||||
|
@ -47,7 +46,7 @@ pub trait ErasedAssetLoader: Send + Sync + 'static {
|
|||
/// Asynchronously loads the asset(s) from the bytes provided by [`Reader`].
|
||||
fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader,
|
||||
reader: &'a mut dyn Reader,
|
||||
meta: Box<dyn AssetMetaDyn>,
|
||||
load_context: LoadContext<'a>,
|
||||
) -> BoxedFuture<
|
||||
|
@ -78,7 +77,7 @@ where
|
|||
/// Processes the asset in an asynchronous closure.
|
||||
fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader,
|
||||
reader: &'a mut dyn Reader,
|
||||
meta: Box<dyn AssetMetaDyn>,
|
||||
mut load_context: LoadContext<'a>,
|
||||
) -> BoxedFuture<
|
||||
|
@ -519,7 +518,7 @@ impl<'a> LoadContext<'a> {
|
|||
path: AssetPath<'static>,
|
||||
meta: Box<dyn AssetMetaDyn>,
|
||||
loader: &dyn ErasedAssetLoader,
|
||||
reader: &mut Reader<'_>,
|
||||
reader: &mut dyn Reader,
|
||||
) -> Result<ErasedLoadedAsset, LoadDirectError> {
|
||||
let loaded_asset = self
|
||||
.asset_server
|
||||
|
|
|
@ -11,16 +11,16 @@ use std::any::TypeId;
|
|||
use std::sync::Arc;
|
||||
|
||||
// Utility type for handling the sources of reader references
|
||||
enum ReaderRef<'a, 'b> {
|
||||
Borrowed(&'a mut Reader<'b>),
|
||||
Boxed(Box<Reader<'b>>),
|
||||
enum ReaderRef<'a> {
|
||||
Borrowed(&'a mut dyn Reader),
|
||||
Boxed(Box<dyn Reader + 'a>),
|
||||
}
|
||||
|
||||
impl<'a, 'b> ReaderRef<'a, 'b> {
|
||||
pub fn as_mut(&mut self) -> &mut Reader {
|
||||
impl ReaderRef<'_> {
|
||||
pub fn as_mut(&mut self) -> &mut dyn Reader {
|
||||
match self {
|
||||
ReaderRef::Borrowed(r) => r,
|
||||
ReaderRef::Boxed(b) => &mut *b,
|
||||
ReaderRef::Borrowed(r) => &mut **r,
|
||||
ReaderRef::Boxed(b) => &mut **b,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,13 +168,13 @@ impl<'ctx, 'builder> UntypedNestedLoader<'ctx, 'builder> {
|
|||
/// - `reader`: the lifetime of the [`Reader`] reference used to read the asset data
|
||||
pub struct DirectNestedLoader<'ctx, 'builder, 'reader> {
|
||||
base: NestedLoader<'ctx, 'builder>,
|
||||
reader: Option<&'builder mut Reader<'reader>>,
|
||||
reader: Option<&'builder mut (dyn Reader + 'reader)>,
|
||||
}
|
||||
|
||||
impl<'ctx: 'reader, 'builder, 'reader> DirectNestedLoader<'ctx, 'builder, 'reader> {
|
||||
/// Specify the reader to use to read the asset data.
|
||||
#[must_use]
|
||||
pub fn with_reader(mut self, reader: &'builder mut Reader<'reader>) -> Self {
|
||||
pub fn with_reader(mut self, reader: &'builder mut (dyn Reader + 'reader)) -> Self {
|
||||
self.reader = Some(reader);
|
||||
self
|
||||
}
|
||||
|
|
|
@ -196,7 +196,7 @@ impl AssetLoader for () {
|
|||
type Error = std::io::Error;
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
_reader: &'a mut crate::io::Reader<'_>,
|
||||
_reader: &'a mut dyn crate::io::Reader,
|
||||
_settings: &'a Self::Settings,
|
||||
_load_context: &'a mut crate::LoadContext<'_>,
|
||||
) -> Result<Self::Asset, Self::Error> {
|
||||
|
|
|
@ -310,7 +310,7 @@ impl<T: AssetLoader> AssetLoader for InstrumentedAssetLoader<T> {
|
|||
|
||||
fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut crate::io::Reader,
|
||||
reader: &'a mut dyn crate::io::Reader,
|
||||
settings: &'a Self::Settings,
|
||||
load_context: &'a mut crate::LoadContext,
|
||||
) -> impl ConditionalSendFuture<Output = Result<Self::Asset, Self::Error>> {
|
||||
|
@ -382,7 +382,7 @@ mod tests {
|
|||
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
_: &'a mut crate::io::Reader<'_>,
|
||||
_: &'a mut dyn crate::io::Reader,
|
||||
_: &'a Self::Settings,
|
||||
_: &'a mut crate::LoadContext<'_>,
|
||||
) -> Result<Self::Asset, Self::Error> {
|
||||
|
|
|
@ -1065,7 +1065,7 @@ impl AssetServer {
|
|||
(
|
||||
Box<dyn AssetMetaDyn>,
|
||||
Arc<dyn ErasedAssetLoader>,
|
||||
Box<Reader<'a>>,
|
||||
Box<dyn Reader + 'a>,
|
||||
),
|
||||
AssetLoadError,
|
||||
> {
|
||||
|
@ -1169,7 +1169,7 @@ impl AssetServer {
|
|||
asset_path: &AssetPath<'_>,
|
||||
meta: Box<dyn AssetMetaDyn>,
|
||||
loader: &dyn ErasedAssetLoader,
|
||||
reader: &mut Reader<'_>,
|
||||
reader: &mut dyn Reader,
|
||||
load_dependencies: bool,
|
||||
populate_hashes: bool,
|
||||
) -> Result<ErasedLoadedAsset, AssetLoadError> {
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
use bevy_asset::{
|
||||
io::{AsyncReadExt, Reader},
|
||||
Asset, AssetLoader, LoadContext,
|
||||
};
|
||||
use bevy_asset::{io::Reader, Asset, AssetLoader, LoadContext};
|
||||
use bevy_reflect::TypePath;
|
||||
use std::{io::Cursor, sync::Arc};
|
||||
|
||||
|
@ -46,7 +43,7 @@ impl AssetLoader for AudioLoader {
|
|||
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
_settings: &'a Self::Settings,
|
||||
_load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<AudioSource, Self::Error> {
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
#[cfg(feature = "bevy_animation")]
|
||||
use bevy_animation::{AnimationTarget, AnimationTargetId};
|
||||
use bevy_asset::{
|
||||
io::Reader, AssetLoadError, AssetLoader, AsyncReadExt, Handle, LoadContext, ReadAssetBytesError,
|
||||
io::Reader, AssetLoadError, AssetLoader, Handle, LoadContext, ReadAssetBytesError,
|
||||
};
|
||||
use bevy_color::{Color, LinearRgba};
|
||||
use bevy_core::Name;
|
||||
|
@ -176,7 +176,7 @@ impl AssetLoader for GltfLoader {
|
|||
type Error = GltfError;
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
settings: &'a GltfLoaderSettings,
|
||||
load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Gltf, Self::Error> {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use bevy_asset::{
|
||||
io::{AsyncReadAndSeek, Reader, Writer},
|
||||
io::{Reader, Writer},
|
||||
saver::{AssetSaver, SavedAsset},
|
||||
Asset, AssetLoader, AsyncReadExt, AsyncWriteExt, LoadContext,
|
||||
};
|
||||
|
@ -85,7 +85,7 @@ impl AssetLoader for MeshletMeshSaverLoad {
|
|||
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
_settings: &'a Self::Settings,
|
||||
_load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Self::Asset, Self::Error> {
|
||||
|
@ -144,9 +144,7 @@ pub enum MeshletMeshSaveOrLoadError {
|
|||
Io(#[from] std::io::Error),
|
||||
}
|
||||
|
||||
async fn read_u64(
|
||||
reader: &mut (dyn AsyncReadAndSeek + Sync + Send + Unpin),
|
||||
) -> Result<u64, bincode::Error> {
|
||||
async fn read_u64(reader: &mut dyn Reader) -> Result<u64, bincode::Error> {
|
||||
let mut bytes = [0u8; 8];
|
||||
reader.read_exact(&mut bytes).await?;
|
||||
Ok(u64::from_le_bytes(bytes))
|
||||
|
|
|
@ -3,7 +3,6 @@ use crate::define_atomic_id;
|
|||
use bevy_asset::{io::Reader, Asset, AssetLoader, AssetPath, Handle, LoadContext};
|
||||
use bevy_reflect::TypePath;
|
||||
use bevy_utils::tracing::error;
|
||||
use futures_lite::AsyncReadExt;
|
||||
use std::{borrow::Cow, marker::Copy};
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -261,7 +260,7 @@ impl AssetLoader for ShaderLoader {
|
|||
type Error = ShaderLoaderError;
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
_settings: &'a Self::Settings,
|
||||
load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Shader, Self::Error> {
|
||||
|
|
|
@ -2,10 +2,7 @@ use crate::{
|
|||
render_asset::RenderAssetUsages,
|
||||
texture::{Image, TextureFormatPixelInfo},
|
||||
};
|
||||
use bevy_asset::{
|
||||
io::{AsyncReadExt, Reader},
|
||||
AssetLoader, LoadContext,
|
||||
};
|
||||
use bevy_asset::{io::Reader, AssetLoader, LoadContext};
|
||||
use image::ImageDecoder;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
@ -37,7 +34,7 @@ impl AssetLoader for ExrTextureLoader {
|
|||
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
settings: &'a Self::Settings,
|
||||
_load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Image, Self::Error> {
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
render_asset::RenderAssetUsages,
|
||||
texture::{Image, TextureFormatPixelInfo},
|
||||
};
|
||||
use bevy_asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext};
|
||||
use bevy_asset::{io::Reader, AssetLoader, LoadContext};
|
||||
use image::DynamicImage;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
@ -32,7 +32,7 @@ impl AssetLoader for HdrTextureLoader {
|
|||
type Error = HdrTextureLoaderError;
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
settings: &'a Self::Settings,
|
||||
_load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Image, Self::Error> {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use bevy_asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext};
|
||||
use bevy_asset::{io::Reader, AssetLoader, LoadContext};
|
||||
use bevy_ecs::prelude::{FromWorld, World};
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -88,7 +88,7 @@ impl AssetLoader for ImageLoader {
|
|||
type Error = ImageLoaderError;
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
settings: &'a ImageLoaderSettings,
|
||||
load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Image, Self::Error> {
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::ron;
|
|||
#[cfg(feature = "serialize")]
|
||||
use crate::serde::SceneDeserializer;
|
||||
use crate::DynamicScene;
|
||||
use bevy_asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext};
|
||||
use bevy_asset::{io::Reader, AssetLoader, LoadContext};
|
||||
use bevy_ecs::reflect::AppTypeRegistry;
|
||||
use bevy_ecs::world::{FromWorld, World};
|
||||
use bevy_reflect::TypeRegistryArc;
|
||||
|
@ -47,7 +47,7 @@ impl AssetLoader for SceneLoader {
|
|||
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
_settings: &'a (),
|
||||
_load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Self::Asset, Self::Error> {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::Font;
|
||||
use bevy_asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext};
|
||||
use bevy_asset::{io::Reader, AssetLoader, LoadContext};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -23,7 +23,7 @@ impl AssetLoader for FontLoader {
|
|||
type Error = FontLoaderError;
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
_settings: &'a (),
|
||||
_load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Font, Self::Error> {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use bevy::{
|
||||
asset::{
|
||||
io::{Reader, VecReader},
|
||||
AssetLoader, AsyncReadExt, ErasedLoadedAsset, LoadContext, LoadDirectError,
|
||||
AssetLoader, ErasedLoadedAsset, LoadContext, LoadDirectError,
|
||||
},
|
||||
prelude::*,
|
||||
reflect::TypePath,
|
||||
|
@ -42,7 +42,7 @@ impl AssetLoader for GzAssetLoader {
|
|||
type Error = GzAssetLoaderError;
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
_settings: &'a (),
|
||||
load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Self::Asset, Self::Error> {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Implements loader for a custom asset type.
|
||||
|
||||
use bevy::{
|
||||
asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext},
|
||||
asset::{io::Reader, AssetLoader, LoadContext},
|
||||
prelude::*,
|
||||
reflect::TypePath,
|
||||
};
|
||||
|
@ -35,7 +35,7 @@ impl AssetLoader for CustomAssetLoader {
|
|||
type Error = CustomAssetLoaderError;
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
_settings: &'a (),
|
||||
_load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Self::Asset, Self::Error> {
|
||||
|
@ -74,7 +74,7 @@ impl AssetLoader for BlobAssetLoader {
|
|||
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
_settings: &'a (),
|
||||
_load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Self::Asset, Self::Error> {
|
||||
|
|
|
@ -15,11 +15,11 @@ use std::path::Path;
|
|||
struct CustomAssetReader(Box<dyn ErasedAssetReader>);
|
||||
|
||||
impl AssetReader for CustomAssetReader {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
info!("Reading {:?}", path);
|
||||
self.0.read(path).await
|
||||
}
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
|
||||
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
|
||||
self.0.read_meta(path).await
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use bevy::{
|
|||
processor::LoadTransformAndSave,
|
||||
saver::{AssetSaver, SavedAsset},
|
||||
transformer::{AssetTransformer, TransformedAsset},
|
||||
AssetLoader, AsyncReadExt, AsyncWriteExt, LoadContext,
|
||||
AssetLoader, AsyncWriteExt, LoadContext,
|
||||
},
|
||||
prelude::*,
|
||||
reflect::TypePath,
|
||||
|
@ -83,7 +83,7 @@ impl AssetLoader for TextLoader {
|
|||
type Error = std::io::Error;
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
settings: &'a TextSettings,
|
||||
_load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<Text, Self::Error> {
|
||||
|
@ -137,7 +137,7 @@ impl AssetLoader for CoolTextLoader {
|
|||
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
reader: &'a mut dyn Reader,
|
||||
_settings: &'a Self::Settings,
|
||||
load_context: &'a mut LoadContext<'_>,
|
||||
) -> Result<CoolText, Self::Error> {
|
||||
|
|
Loading…
Reference in a new issue