Skip to content

bevy_asset: support upgrading Reader to SeekableReader#22182

Merged
cart merged 10 commits intobevyengine:mainfrom
cart:seekable_reader
Jan 7, 2026
Merged

bevy_asset: support upgrading Reader to SeekableReader#22182
cart merged 10 commits intobevyengine:mainfrom
cart:seekable_reader

Conversation

@cart
Copy link
Member

@cart cart commented Dec 18, 2025

Objective

#22104 added AsyncSeek support, but it has some downsides:

  • It is very "loose": it relies on AssetLoader to "attest" that it needs the seek feature. However, AssetLoaders both have access to the AsyncSeek API no matter what (it is a supertrait of Reader), and AssetReaders provide AsyncSeek behavior even if it isn't requested. In practice this is likely to create situations where AssetLoaders don't request AsyncSeek and just rely on it being provided by default, causing unexpected incompatibilities when AssetLoader consumers try to use other AssetReaders that don't support AsyncSeek.
  • It encourages building "fallback" behavior into the AssetReader in cases where AsyncSeek cannot be supported directly (ex: read the while contents into a Vec). From the perspective of loaders, this silently changes the performance characteristics, and forces a specific kind of fallback behavior. It would be better if the fallback behavior was in the hands of the AssetLoader.

Solution

  • Remove ReaderRequiredFeatures and associated functionality
  • Add a new SeekableReader trait, where SeekableReader: Reader + AsyncSeek.
  • Add a new Reader::seekable(&mut self) -> Result<&mut dyn SeekableReader, ReaderNotSeekableError>, which can either fail or cast to SeekableReader, if that is supported.
let seekable_reader = reader.seekable()?;
seekable_reader.seek(SeekFrom::Start(10)).await?;

This gives AssetLoader implementers more clarity when it comes to Reader feature support, gives them more autonomy over fallback behavior, makes our APIs more static, and cuts down on the complexity of the system as a whole.

@cart cart added this to the 0.18 milestone Dec 18, 2025
@cart cart added C-Feature A new feature, making something new possible A-Assets Load files from disk to use for things like images, models, and sounds C-Usability A targeted quality-of-life change that makes Bevy easier to use labels Dec 18, 2025
Copy link
Contributor

@andriyDev andriyDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but we need to delete the remnants: android, wasm, and web modules need to be cleaned up, custom_asset_reader example also need to be cleaned up. Also some migration guides we need to update (we can leave this until later).

@cart
Copy link
Member Author

cart commented Dec 18, 2025

Also some migration guides we need to update (we can leave this until later)

I updated these (and release notes) right before you posted 😄

@alice-i-cecile alice-i-cecile added the S-Needs-Review Needs reviewer attention (from anyone!) to move forward label Dec 18, 2025
Copy link
Contributor

@andriyDev andriyDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved but for the doctest, which I've made a PR against this branch for: cart#50

Thanks for taking the time to fix this!!

Copy link
Member

@janhohenheim janhohenheim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks much cleaner to me, good job! The PR introduces some new public API that is missing documentation. Approving after that :)

@janhohenheim janhohenheim added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Dec 18, 2025
@cart cart changed the base branch from main to release-0.18.0 January 7, 2026 20:59
@cart cart changed the base branch from release-0.18.0 to main January 7, 2026 20:59
@cart
Copy link
Member Author

cart commented Jan 7, 2026

(just checking to see what backporting will look like in terms of conflicts)

@cart cart enabled auto-merge January 7, 2026 21:21
@cart cart added this pull request to the merge queue Jan 7, 2026
Merged via the queue into bevyengine:main with commit cd977df Jan 7, 2026
38 checks passed
cart added a commit that referenced this pull request Jan 8, 2026
- It is very "loose": it relies on `AssetLoader` to "attest" that it
needs the seek feature. However, AssetLoaders both have access to the
`AsyncSeek` API no matter what (it is a supertrait of Reader), and
AssetReaders provide `AsyncSeek` behavior even if it isn't requested. In
practice this is likely to create situations where AssetLoaders don't
request `AsyncSeek` and just rely on it being provided by default,
causing unexpected incompatibilities when AssetLoader consumers try to
use other AssetReaders that don't support AsyncSeek.
- It encourages building "fallback" behavior into the AssetReader in
cases where AsyncSeek cannot be supported directly (ex: read the while
contents into a Vec). From the perspective of loaders, this _silently_
changes the performance characteristics, and _forces_ a specific kind of
fallback behavior. It would be better if the fallback behavior was in
the hands of the AssetLoader.

- Remove `ReaderRequiredFeatures` and associated functionality
- Add a new `SeekableReader` trait, where `SeekableReader: Reader +
AsyncSeek`.
- Add a new `Reader::seekable(&mut self) -> Result<&mut dyn
SeekableReader, ReaderNotSeekableError>`, which can either fail or cast
to `SeekableReader`, if that is supported.

```rust
let seekable_reader = reader.seekable()?;
seekable_reader.seek(SeekFrom::Start(10)).await?;
```

This gives `AssetLoader` implementers more clarity when it comes to
`Reader` feature support, gives them more autonomy over fallback
behavior, makes our APIs more static, and cuts down on the complexity of
the system as a whole.

---------

Co-authored-by: andriyDev <andriydzikh@gmail.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
/// An [`AsyncRead`] implementation capable of reading a [`Vec<u8>`].
pub struct VecReader {
bytes: Vec<u8>,
/// The bytes being read. This is the full original list of bytes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These docs suggest that bytes should be readonly, which makes me think it should have stayed private with an accessor function.

@greeble-dev
Copy link
Contributor

greeble-dev commented Jan 8, 2026

Noticed a couple of issues with this PR on the 0.18.0 branch. I can make a PR to clean them up if requested. EDIT: Decided to go ahead without request.

Firstly, compile error related to InstrumentedAssetLoader if trace feature is enabled:

error[E0432]: unresolved import `crate::io::ReaderRequiredFeatures`
  --> crates\bevy_asset\src\server\loaders.rs:18:5
   |
18 |     crate::io::ReaderRequiredFeatures,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `ReaderRequiredFeatures` in `io`

InstrumentedAssetLoader has been removed in main but still exists in 0.18.

Also noticed some release content that references ReaderRequiredFeatures - I think they should have been removed by this PR?

image

@greeble-dev
Copy link
Contributor

Followed up previous comment in #22430.

alice-i-cecile pushed a commit that referenced this pull request Jan 8, 2026
`ReaderRequiredFeatures` was added by #22104 and removed by #22182, but
[some
references](#22182 (comment))
snuck into the 0.18 branch. This was causing a compile error if the
`trace` feature was enabled, and some release content was misleading.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Assets Load files from disk to use for things like images, models, and sounds C-Feature A new feature, making something new possible C-Usability A targeted quality-of-life change that makes Bevy easier to use S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants