A Love Wins Media product

Engineering plans / Active (pilot on the embed worker) · November 3, 2026

Swift and Rust interop

The XPC services are moving their work into Rust (Rust components and reader plugins). Each crate so far crosses into Swift through a C ABI with JSON requests and replies. The ABI is static and loads nothing at run time, but its headers and its JSON shapes are kept by hand on both sides.

Rick chose the three tools below on 2026-11-03: “lets start with cbindgen and swift-rs”, followed by a UniFFI pilot for the XPC hosts.

Direction and use Tool Why
A reader plugin’s C ABI (garage_text.h): protobuf bytes in and out, for Swift, .NET and Python’s ctypes alike cbindgen The contract is the proto. The header only carries bytes, so generating it from the Rust is all it needs.
An XPC service calling its Rust worker (embed, ingest, MCP): wide APIs, many host callbacks UniFFI Typed records, enums and errors in place of hand-kept JSON. The host’s callbacks become a Swift protocol. Python bindings come with it, and C# through a community generator.
Rust calling a Swift-only Apple API (Vision’s RecognizeDocumentsRequest) swift-rs An @_cdecl Swift function, declared in Rust with swift!, which balances the retain counts of what crosses.

cbindgen

UniFFI: the embed worker pilot

rust/garage-embed-uniffi exposes the same three calls as garage_embed.h (backfill, models, embed_texts) with:

It sits beside the C ABI, which GarageEmbedWorker still uses, so nothing changes until the Swift host switches.

If the pilot holds, the ingest and MCP hosts follow, one crate at a time, each keeping its C ABI until its host has moved.

swift-rs

garage-ocr’s vision-documents feature is the first use: Rust calls Vision’s Swift-only RecognizeDocumentsRequest through garage_ocr_recognize_document (see OCR for the Rust ingester).