Skip to content

Allow Reader to implement AsyncSeek and provide a way for loaders to "ask" for a compatible reader.#22104

Merged
cart merged 17 commits intobevyengine:mainfrom
andriyDev:seek
Dec 16, 2025
Merged

Allow Reader to implement AsyncSeek and provide a way for loaders to "ask" for a compatible reader.#22104
cart merged 17 commits intobevyengine:mainfrom
andriyDev:seek

Conversation

@andriyDev
Copy link
Contributor

@andriyDev andriyDev commented Dec 13, 2025

Objective

Solution

  • Allow AssetLoader to say which "features" of a reader it needs.
  • Pass that list of features to AssetReader so it can decide how to handle it.
  • Add a new AssetReaderError::UnsupportedFeature.

This design is kind of "weak" - there's no guarantee that a loader that requests AnySeek will get a reader that actually implements AsyncSeek. Or on the other side, there's no guarantee that a loader actually requests the features that it uses. However, in practice it's likely enough: errors are likely to guide users to the correct situation. In the future, we could perhaps have a "sieve reader", which blocks any features the loader didn't explicitly request. Perhaps this is a debug only feature, or something that can be toggled.

Testing

  • Ran the modified examples. They still seem to work!

@andriyDev andriyDev 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 M-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide M-Release-Note Work that should be called out in the blog due to impact D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Dec 13, 2025
@andriyDev andriyDev force-pushed the seek branch 3 times, most recently from f515166 to 8c5977d Compare December 13, 2025 08:39
Copy link
Contributor

@atlv24 atlv24 left a comment

Choose a reason for hiding this comment

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

nice job, looks good to me

@janhohenheim janhohenheim added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Dec 13, 2025
@andriyDev andriyDev removed the S-Needs-Review Needs reviewer attention (from anyone!) to move forward label Dec 14, 2025
Copy link
Member

@cart cart left a comment

Choose a reason for hiding this comment

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

I see the vision, and I think this makes the right UX tradeoff. The alternative is forking out a separate set of AssetLoader traits, which would be a big UX downgrade.

The big "risk" here is that loaders won't request seeking behavior by default, but they will get seeking behavior by default. Then when they are used in a non-seeking context, they will fail at runtime. I expect this to be a common source of bugs in practice.

The big use case here is skipping the intermediate "read into buffer" behavior for the web / wasm providers, when a loader doesnt request seekability. If we start doing that, then loaders that don't request the appropriate feature will fail at load-time. Fortunately, I think this is the kind of thing that will be caught quickly. If/when we land that, we'll probably want a break-glass configuration item that devs can use to force seekability via the intermediate Vec, so they can quickly work around offending loaders they don't control.

I just removed all of the unnecessary "default" impls to cut down on the noise. I also merged with main.

@cart cart enabled auto-merge December 16, 2025 03:27
@cart cart added this pull request to the merge queue Dec 16, 2025
Merged via the queue into bevyengine:main with commit c92867a Dec 16, 2025
36 checks passed
blamelessgames pushed a commit to blamelessgames/bevy that referenced this pull request Jan 7, 2026
)

# Objective

bevyengine#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.

```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>
greeble-dev added a commit to greeble-dev/bevy that referenced this pull request Jan 8, 2026
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 D-Straightforward Simple bug fixes and API improvements, docs, test and examples M-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide M-Release-Note Work that should be called out in the blog due to impact S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AsyncSeek trait bound on Reader may limit options to stream bytes

5 participants