#filetype #macos #mime

uti

Safe Rust bindings for Apple's UniformTypeIdentifiers framework — file-type / MIME identification on macOS

10 releases (4 breaking)

0.5.2 Jun 6, 2026
0.5.1 May 20, 2026
0.4.4 May 20, 2026
0.3.0 May 16, 2026
0.1.0 May 15, 2026

#375 in macOS and iOS APIs

MIT/Apache

110KB
2K SLoC

Rust 1K SLoC // 0.0% comments Swift 691 SLoC

uti

Safe Rust bindings for Apple's UniformTypeIdentifiers framework on macOS — file-type and MIME identification via UTType.

Status: v0.5.0 keeps the MacOSX26.5.sdk audit clean and adds true async NSItemProvider typed loaders behind the optional async feature. See COVERAGE.md.

Quick start

use uti::prelude::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Look up by extension, MIME, or full identifier.
    let png  = UTI::from_filename_extension("png")?;
    let json = UTI::from_mime_type("application/json")?;
    let pdf  = UTI::from_identifier("com.adobe.pdf")?;
    let png_code = os_type::encode("PNGf")?;

    println!("png  identifier: {}", png.identifier());
    println!("png  mime:       {:?}", png.preferred_mime_type());
    println!("png  description:{:?}", png.localized_description());
    println!("json extension:  {:?}", json.preferred_filename_extension());
    println!("pdf  is_public:  {}", pdf.is_public());
    println!("png  ostype:     {:?}", png.preferred_os_type_string());
    assert_eq!(UTI::from_os_type(png_code)?.identifier(), png.identifier());

    // Conformance: PNG conforms to image, image conforms to data.
    let image = UTI::well_known("image").unwrap();
    let data  = UTI::well_known("data").unwrap();
    assert!(png.conforms_to(&image));
    assert!(png.conforms_to(&data));
    Ok(())
}

Async ItemProvider

Enable features = ["async"] for runtime-neutral wrappers around NSItemProvider's typed completion-handler loading APIs.

# #[cfg(feature = "async")]
# fn main() -> Result<(), Box<dyn std::error::Error>> { pollster::block_on(async {
use uti::{async_api::AsyncItemProvider, ItemProvider, RepresentationVisibility, UTI};

let provider = ItemProvider::new();
let plain_text = UTI::well_known("plainText").unwrap();
provider.register_data_representation(
    &plain_text,
    RepresentationVisibility::OwnProcess,
    b"hello from async item provider",
);

let bytes = AsyncItemProvider::new(&provider)
    .load_data_representation(&plain_text)
    .await?;
assert_eq!(bytes, b"hello from async item provider");
# Ok(()) }) }
# #[cfg(not(feature = "async"))]
# fn main() {}

See examples/07_item_provider_async.rs for a full data + file example.

Pipeline composition

imageio (open file) ──► uti (identify format) ──► dispatch to right pipeline
                                                    │
                                                    ├─► PNG/JPEG -> apple-vision OCR
                                                    ├─► WAV/MP3  -> soundanalysis
                                                    ├─► PDF      -> pdfkit (planned)
                                                    └─► TXT      -> naturallanguage

UTI is foundational — every doom-fish crate that takes a file path can use it to dispatch on format before invoking the right pipeline.

Roadmap

  • UTI::from_identifier(...), from_filename_extension(...), from_mime_type(...), generic from_tag(...), and multi-match helpers for filename extensions / MIME types / OSType tags
  • Accessors: identifier, preferred_filename_extension, preferred_mime_type, localized_description, version, version_number, reference_url, tags, filename_extensions, mime_types, preferred_os_type, os_types
  • Conformance: conforms_to, is_supertype_of, is_subtype_of, supertypes, equality
  • State queries: is_dynamic, is_declared, is_public_type, is_public
  • Swift / Obj-C naming aliases: UTType, UTTypeReference
  • Full UTCoreTypes.h coverage via core_types::* + UTI::well_known(name)
  • UTTagClass constants via tag_class::FILENAME_EXTENSION, tag_class::MIME_TYPE, plus crate convenience tag_class::OS_TYPE
  • OSType / FourCharCode encoding helpers via uti::os_type
  • UTAdditions helpers via uti::additions
  • NSItemProvider integration via ItemProvider, plus non-blocking typed loaders via async_api / ItemProvider::*_async (async feature)
  • SDK coverage tests, smoke tests, and COVERAGE.md audit output

License

Licensed under either of Apache-2.0 or MIT at your option.

Dependencies

~0.6–0.9MB
~15K SLoC