photokit 0.4.0

Safe Rust bindings for Apple's Photos framework — photo library access on macOS
Documentation

photokit

Safe Rust bindings for Apple's Photos framework on macOS.

Status: v0.3.0 adds the Tier-1 async_api module on top of the fully audited Photos.framework surface, with executor-agnostic futures for authorization, performChanges, image requests, and live-photo editing callbacks.

Quick start

use photokit::prelude::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let library = PHPhotoLibrary::shared()?;
    println!("status: {:?}", PHPhotoLibrary::authorization_status());

    let assets = PHAsset::fetch(&PHFetchOptions::default())?;
    println!("assets: {}", assets.len());

    if let Some(asset) = assets.first() {
        let manager = PHImageManager::shared()?;
        let request = manager.request_image_data(
            asset,
            &PHImageRequest::new(320.0, 240.0, PHImageContentMode::AspectFit),
        )?;
        let image = request.wait(10_000)?;
        println!("image bytes: {}", image.data().len());
    }

    let _ = library.fetch_asset_collections(&PHFetchOptions::default())?;
    Ok(())
}

Async API

Enable the async feature to access non-blocking wrappers for Photos.framework completion-handler APIs:

[dependencies]
photokit = { version = "0.3", features = ["async"] }
use photokit::async_api::AsyncPHPhotoLibrary;
use photokit::PHAccessLevel;

# async fn demo() -> Result<(), Box<dyn std::error::Error>> {
let status = AsyncPHPhotoLibrary::request_authorization(PHAccessLevel::ReadWrite).await?;
# Ok(())
# }

All async types implement std::future::Future and are executor-agnostic. See async_api for the full API surface.

Highlights

  • PHPhotoLibrary authorization helpers plus summary/detailed change observers, availability observers, and persistent-change history helpers.
  • PHAsset, PHCollection, PHAssetCollection, and PHCollectionList fetch helpers with typed subtype/source/resource wrappers.
  • PHChangeRequest builders for asset, album, folder, and project mutation flows.
  • PHImageManager / PHCachingImageManager request handles for images, image data, live photos, video requests, and caching.
  • PHAssetResourceManager transfer helpers for reading or writing asset resources.
  • PHContentEditingInput / PHContentEditingOutput plus PHLivePhotoEditingContext for non-destructive editing workflows.
  • PHCloudIdentifier batch lookup helpers and richer Photos-specific error metadata.

Coverage audit

See COVERAGE.md for the framework audit, implemented rows, partial rows, and deferred macOS-unavailable or deprecated APIs.

Examples

The crate ships with numbered examples covering every logical area:

  • 01_photokit_smoke
  • 02_phasset_fetch
  • 03_phasset_collection_fetch
  • 04_phcollection_list_fetch
  • 05_phphoto_library_authorization
  • 06_phimage_manager_requests
  • 07_phfetch_result_methods
  • 08_phchange_observer
  • 09_phcontent_editing_input
  • 10_phcontent_editing_output
  • 11_phobject_change_details
  • 12_phfetch_options_builder
  • 13_phasset_creation_request
  • 14_phlive_photo
  • 15_phcloud_identifier
  • 16_async_api (requires --features async)

Run them with:

for ex in examples/*.rs; do
  name="$(basename "$ex" .rs)"
  if [ "$name" = "16_async_api" ]; then
    cargo run --example "$name" --features async
  else
    cargo run --example "$name"
  fi
done

Verification

cargo clippy --all-features --all-targets -- -D warnings
cargo test --all-features
for ex in examples/*.rs; do
  name="$(basename "$ex" .rs)"
  if [ "$name" = "16_async_api" ]; then
    cargo run --example "$name" --features async
  else
    cargo run --example "$name"
  fi
done

License

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