Skip to content

Add Wasm support for AsyncMediaSource#53

Merged
mindeng merged 1 commit into
mindeng:mainfrom
Enduriel:main
May 28, 2026
Merged

Add Wasm support for AsyncMediaSource#53
mindeng merged 1 commit into
mindeng:mainfrom
Enduriel:main

Conversation

@Enduriel
Copy link
Copy Markdown
Contributor

Closes #52, option A as discussed in that issue.

@mindeng
Copy link
Copy Markdown
Owner

mindeng commented May 14, 2026

Code review

Found 2 issues:

  1. cargo test --no-default-features --features tokio no longer compiles. The PR re-gates AsyncMediaSource::open, read_exif_async, read_exif_iter_async, read_metadata_async, and read_track_async to feature = "tokio-fs", but several #[cfg(feature = "tokio")] call sites still reference these now-tokio-fs-only symbols. Reproduced locally — 18+ E0599 / E0425 errors. Sites needing the gate widened to tokio-fs (or per-fn cfgs):
  • Test mod at
    #[cfg(test)]
    mod tests {
    use std::path::Path;
    use super::*;
    use crate::{ExifIter, TrackInfo};
    use test_case::case;
    enum TrackExif {
    Track,
    Exif,
    NoData,
    Invalid,
    }
    use tokio::fs::File;
    use TrackExif::*;
    #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
    uses tokio::fs::File and AsyncMediaSource::open under #[cfg(test)].
  • nom-exif/src/lib.rs

    Lines 395 to 408 in ba2a417

    #[cfg(feature = "tokio")]
    #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
    async fn read_exif_async_jpg() {
    let exif = read_exif_async("testdata/exif.jpg").await.unwrap();
    assert!(exif.get(ExifTag::Make).is_some());
    }
    #[cfg(feature = "tokio")]
    #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
    async fn read_track_async_mov() {
    let info = read_track_async("testdata/meta.mov").await.unwrap();
    assert!(info.get(TrackInfoTag::Make).is_some());
    }
    — async test helpers gated only on tokio.
  • #[cfg(feature = "tokio")]
    #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
    async fn s5_8_async_top_level_helper() {
    let exif = read_exif_async("./testdata/exif.jpg").await.unwrap();
    assert!(exif.get(ExifTag::Make).is_some());
    }
    #[cfg(feature = "tokio")]
    #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
    async fn s5_8_async_media_parser_method() {
    let mut parser = MediaParser::new();
    let ms = AsyncMediaSource::open("./testdata/exif.jpg").await.unwrap();
    let _iter = parser.parse_exif_async(ms).await.unwrap();
    }
  • nom-exif/tests/png.rs

    Lines 60 to 67 in ba2a417

    #[cfg(feature = "tokio")]
    #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
    async fn parse_image_metadata_async_exif_png() {
    use nom_exif::AsyncMediaSource;
    let mut parser = MediaParser::new();
    let ms = AsyncMediaSource::open("testdata/exif.png").await.unwrap();
    let img = parser.parse_image_metadata_async(ms).await.unwrap();
  1. Silent breaking change for current features = ["tokio"] users, with crate docs and README left advertising the old gate. Any downstream consumer calling read_exif_async / AsyncMediaSource::open under features = ["tokio"] will get unresolved-symbol errors on upgrade. The breakage is acknowledged in Wasm support for AsyncMediaSource #52 as "mildly breaking" — please pair the split with a CHANGELOG entry and update the rustdoc + README that still claim the old gate:

nom-exif/src/lib.rs

Lines 55 to 59 in ba2a417

//!
//! Async variants live behind `feature = "tokio"`:
//! [`read_exif_async`], [`read_track_async`], [`read_metadata_async`],
//! plus [`MediaParser::parse_exif_async`] / [`MediaParser::parse_track_async`].
//!

nom-exif/src/lib.rs

Lines 150 to 156 in ba2a417

//!
//! # Cargo features
//!
//! - `tokio` — async API via tokio (`AsyncMediaSource`, `read_*_async`,
//! `MediaParser::parse_*_async`).
//! - `serde` — derives `Serialize`/`Deserialize` on the public types.

nom-exif/README.md

Lines 216 to 244 in ba2a417

```
## Async API
Enable the `tokio` feature in your `Cargo.toml`:
```toml
[dependencies]
nom-exif = { version = "3", features = ["tokio"] }
```
Then use the `_async` helpers, or call `parse_exif_async` /
`parse_track_async` on a `MediaParser` directly:
```rust,no_run
# #[cfg(feature = "tokio")]
# async fn demo() -> nom_exif::Result<()> {
use nom_exif::{read_exif_async, MediaParser, AsyncMediaSource};
// One-shot:
let exif = read_exif_async("./testdata/exif.jpg").await?;
// Reusable:
let mut parser = MediaParser::new();
let ms = AsyncMediaSource::open("./testdata/exif.jpg").await?;
let iter = parser.parse_exif_async(ms).await?;
# let _ = (exif, iter); Ok(())
# }
```

Cargo.toml still on 3.4.1 (already released) — bump before publishing:

nom-exif/Cargo.toml

Lines 1 to 7 in ba2a417

[package]
name = "nom-exif"
rust-version = "1.83"
version = "3.4.1"
edition = "2021"
license-file = "LICENSE"
description = "Exif/metadata parsing library written in pure Rust, both image (jpeg/heif/heic/jpg/tiff etc.) and video/audio (mov/mp4/3gp/webm/mkv/mka, etc.) files are supported."

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@Enduriel
Copy link
Copy Markdown
Contributor Author

Yeah that's my bad, this was pretty quickly put together just to get it working on my side (which it does btw, ty for all your help in that regard).

I'll clean all this up and request another review

so that wasm32-unknown-unknown and similar targets
can use the tokio feature for AsyncMediaSource
@codecov
Copy link
Copy Markdown

codecov Bot commented May 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.84%. Comparing base (dad49e0) to head (f9b6480).

Additional details and impacted files
@@           Coverage Diff           @@
##             main      #53   +/-   ##
=======================================
  Coverage   89.84%   89.84%           
=======================================
  Files          38       38           
  Lines        8399     8399           
=======================================
  Hits         7546     7546           
  Misses        853      853           
Flag Coverage Δ
nom-exif 89.84% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Enduriel
Copy link
Copy Markdown
Contributor Author

Should have everything you previously mentioned fixed. Let me know if you have any other concerns/suggestions.

@mindeng mindeng merged commit 6ab4e65 into mindeng:main May 28, 2026
5 checks passed
@mindeng
Copy link
Copy Markdown
Owner

mindeng commented May 28, 2026

Thanks for both contributions! The tokio/tokio-fs split (#53) and the slice coercion fix (#58) are now included in nom-exif v3.6.0, just published to crates.io. Appreciate the help!

@Enduriel
Copy link
Copy Markdown
Contributor Author

@mindeng Thanks for your quick responses! One thing that might be an issue is that if my understanding is correct this PR should be a SemVer breaking change, and people updating from 3.5 to 3.6 may have issues. I added the ! in the conventional commit to signal that, but I now realize that may not be obvious.

Not sure how you want to resolve this but going by strictly semver rules this should probably be a 4.0.0 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wasm support for AsyncMediaSource

2 participants