Skip to content

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 :)

/// An [`AsyncRead`] implementation capable of reading a [`Vec<u8>`].
pub struct VecReader {
bytes: Vec<u8>,
pub bytes: Vec<u8>,
Copy link
Member

@janhohenheim janhohenheim Dec 18, 2025

Choose a reason for hiding this comment

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

Would you mind adding docs to this struct now that it's pub? How is a user meant to mutate this field? When? Is there anything to keep in mind, or can the user just freely mutate the Vec? Does read_bytes get affected by this?

fn seekable(&mut self) -> Result<&mut dyn SeekableReader, ReaderNotSeekableError>;
}

pub trait SeekableReader: Reader + AsyncSeek {}
Copy link
Member

@janhohenheim janhohenheim Dec 18, 2025

Choose a reason for hiding this comment

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

Could you add some documentation and breadcrumbs to other related traits? Nothing big.

Comment on lines +146 to +150
#[derive(Error, Debug, Copy, Clone)]
#[error(
"The `Reader` returned by the current `AssetReader` does not support `AsyncSeek` behavior."
)]
pub struct ReaderNotSeekableError;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
#[derive(Error, Debug, Copy, Clone)]
#[error(
"The `Reader` returned by the current `AssetReader` does not support `AsyncSeek` behavior."
)]
pub struct ReaderNotSeekableError;
/// Error returned by [`Reader::seekable`] when the reader implementation does not support [`AsyncSeek`] behavior.
#[derive(Error, Debug, Copy, Clone)]
#[error(
"The `Reader` returned by the current `AssetReader` does not support `AsyncSeek` behavior."
)]
pub struct ReaderNotSeekableError;

@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
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.

4 participants