Expand description
nom-exif is a pure Rust library for both image EXIF and
video / audio track metadata through a single unified API.
§Highlights
- Pure Rust — no FFmpeg, no libexif, no system deps; cross-compiles cleanly.
- Image and video / audio in one crate —
MediaParserdispatches to the right backend by detected MIME, no per-format wrappers. - RAW format support — Canon CR3, Fujifilm RAF, Phase One IIQ, alongside JPEG / HEIC / TIFF.
- Three input modes — files, arbitrary
Read/Read + Seek(network streams, pipes), or in-RAM bytes (WASM, mobile, HTTP proxies). - Sync and async unified under one
MediaParser. - Eager (
Exif, get-by-tag) or lazy (ExifIter, parse-on-demand) — per-entry errors surface in both modes (Exif::errors/ per-iterResult), so one bad tag doesn’t poison the parse. - Allocation-frugal — parser buffer is recycled across calls; sub-IFDs share the same allocation (no deep copies).
- Fuzz-tested with
cargo-fuzzagainst malformed and adversarial input.
§Quick start
For a one-shot read, use the helpers:
use nom_exif::{read_exif, ExifTag};
let exif = read_exif("./testdata/exif.jpg")?;
let make = exif.get(ExifTag::Make).and_then(|v| v.as_str());
assert_eq!(make, Some("vivo"));For batch processing, build a MediaParser once and reuse its
buffer:
use nom_exif::{MediaKind, MediaParser, MediaSource};
let mut parser = MediaParser::new();
for path in ["./testdata/exif.jpg", "./testdata/meta.mov"] {
let ms = MediaSource::open(path)?;
match ms.kind() {
MediaKind::Image => { let _ = parser.parse_exif(ms)?; }
MediaKind::Track => { let _ = parser.parse_track(ms)?; }
}
}Async variants live behind feature = "tokio":
read_exif_async, read_track_async, read_metadata_async,
plus MediaParser::parse_exif_async / MediaParser::parse_track_async.
§Reading from in-memory bytes
When the payload is already in RAM (WASM, mobile, HTTP proxy, decoded
response body), use the *_from_bytes helpers to skip the File /
Read round-trip entirely. Memory mode is zero-copy: the underlying
allocation is shared with the returned Exif / ExifIter /
TrackInfo via bytes::Bytes reference counting.
use nom_exif::{read_exif_from_bytes, ExifTag};
let raw = std::fs::read("./testdata/exif.jpg")?;
let exif = read_exif_from_bytes(raw)?;
assert_eq!(exif.get(ExifTag::Make).and_then(|v| v.as_str()), Some("vivo"));For batch processing of many in-memory payloads, build a MediaParser
once and call MediaParser::parse_exif_from_bytes /
MediaParser::parse_track_from_bytes per payload.
§API surface
- One-shot helpers:
read_exif,read_exif_iter,read_track,read_metadatafor files;read_exif_from_bytes,read_exif_iter_from_bytes,read_track_from_bytes,read_metadata_from_bytesfor in-memory bytes. - Reusable parser:
MediaParser+MediaSource(orAsyncMediaSource) - Image metadata:
Exif(eager, get-by-tag) orExifIter(lazy iterator with per-entry errors). Convert:let exif: Exif = iter.into();. - Track metadata:
TrackInfo(audio/video container metadata). - Discriminated union:
Metadatareturned byread_metadata. - Errors:
Errorfor parse-level,EntryErrorfor per-entry IFD errors,ConvertErrorfor type-conversion peer errors. - Convenience:
preludere-exports the symbols you most often need.
See docs/MIGRATION.md for the v2 → v3 migration guide and
docs/V3_API_DESIGN.md for the internal design contract.
§Cargo features
tokio— async API via tokio (AsyncMediaSource,read_*_async,MediaParser::parse_*_async).serde— derivesSerialize/Deserializeon the public types.
§Embedded media
Some formats (HEIC Live Photos, RAF JPEG previews, …) embed media
streams that parse_exif does not surface. The
Exif::has_embedded_media / ExifIter::has_embedded_media /
TrackInfo::has_embedded_media flags let callers detect this; the
actual extraction API is a v3.x deliverable.
Modules§
- prelude
- Convenient one-line import of the most common v3 symbols.
Structs§
- Async
Media Source - Exif
- Represents parsed Exif information, can be converted from an
ExifIterlike this:let exif: Exif = iter.into(). - Exif
Entry - Eager view into a single Exif entry. Yielded by
crate::Exif::iterand designed to be cheap to copy: thevalueis a borrow into the parentcrate::Exif. - Exif
Iter - An iterator version of
Exif. UseExifIterEntryas iterator items. - Exif
Iter Entry - Lazy yield from
ExifIter. Carries a value xor error invariant — every entry holds exactly one ofSelf::valueorSelf::error. - GPSInfo
- Parsed GPS information from the GPSInfo subIFD.
- IfdIndex
- Index of an IFD (Image File Directory) within an EXIF blob.
- LatLng
- Latitude or longitude expressed as degrees / minutes / seconds.
- Media
Parser - A
MediaParsercan parse media info from aMediaSource. - Media
Source MediaSourcerepresents a media data source that can be parsed byMediaParser.- Rational
- Speed
- EXIF GPS speed: unit + value paired so they cannot drift out of sync.
- Track
Info - Represents parsed track info.
Enums§
- Altitude
- Altitude relative to sea level.
- Convert
Error - Errors from conversions that are orthogonal to file parsing: parsing a tag
name from a string, narrowing an
IRationalinto aURational, building aLatLngfrom decimal degrees, parsing an ISO 6709 coordinate string. - Entry
Error - Errors that occur while decoding a single IFD entry.
- Entry
Value - Represent a parsed entry value.
- Error
- Top-level error returned by
read_exif,MediaParser::parse_*,MediaSource::open, and any other public function that touches a file. - Exif
Date Time - EXIF datetime value with timezone awareness preserved.
- ExifTag
- Defines recognized Exif tags. All tags can be parsed, no matter if it is defined here. This enum definition is just for ease of use.
- LatRef
- Latitude hemisphere reference.
- LonRef
- Longitude hemisphere reference.
- Malformed
Kind - Categorizes the structural unit that produced a
Error::Malformed. - Media
Kind - Top-level classification of a media source.
- Metadata
- One-shot result of
read_metadata: either Exif (image) or TrackInfo (video/audio). Closed enum — see spec §8.6 for why there’s noBothvariant. - Speed
Unit - EXIF GPS speed reference unit (
GPSSpeedRef). - TagOr
Code - Either a recognized
ExifTagor a rawu16tag code that the parser did not recognize. Yielded bycrate::ExifIterEntry::tagand bycrate::ExifEntry::tag. - Track
Info Tag - Try to keep the tag name consistent with
crate::ExifTag, and add some unique to video/audio, such asDurationMs.
Functions§
- read_
exif - Read EXIF metadata from a file in a single call.
- read_
exif_ async - read_
exif_ from_ bytes - Read EXIF metadata from an in-memory byte payload in a single call.
Zero-copy: the underlying allocation is shared with the returned
Exifviabytes::Bytesreference counting. - read_
exif_ iter - Read EXIF metadata from a file as a lazy iterator. Like
read_exifbut returns anExifIterso per-entry errors can be inspected and values fetched without materializing the fullExifmap. - read_
exif_ iter_ async - read_
exif_ iter_ from_ bytes - Read EXIF metadata from an in-memory byte payload as a lazy iterator.
Like
read_exif_from_bytesbut returns anExifIter. - read_
metadata - Read metadata from a file, dispatching by detected
MediaKind: images returnMetadata::Exif, video / audio containers returnMetadata::Track. - read_
metadata_ async - read_
metadata_ from_ bytes - Read metadata from an in-memory payload, dispatching by detected
MediaKind: images returnMetadata::Exif, video/audio containers returnMetadata::Track. - read_
track - Read track metadata from a video / audio file in a single call.
- read_
track_ async - read_
track_ from_ bytes - Read track metadata from an in-memory video/audio payload.