uniffi-boundary

Designs and reviews the exported Rust surface of UniFFI crates generating Kotlin and Swift bindings.

2|1|Updated Aug 19, 2026
One-click install
npx skills add https://github.com/po4yka/rust-skills --skill uniffi-boundary-po4yka
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: uniffi-boundary
Source: https://github.com/po4yka/rust-skills/tree/main/skills/uniffi-boundary
Command: npx skills add https://github.com/po4yka/rust-skills --skill uniffi-boundary-po4yka

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve? Shaping the exported API of a UniFFI boundary crate is error-prone: wrong Record versus Object choices, non-Send/Sync state, borrowed returns, panics reaching foreign callers, and cryptic bindgen errors all break Kotlin and Swift consumers. This Skill provides the decision rules, version floors, and error triage tables needed to author or review that surface correctly. ## Core Features & Use Cases - Surface design rules: Decide between uniffi::Object and uniffi::Record, enforce Send + Sync on exported Objects, and apply ownership rules for Arc handles, borrowed arguments, and &[u8] buffers. - Foreign callbacks and async exports: Implement ProgressListener-style foreign traits with proper error mapping, and configure async exports with the correct Tokio runtime attribute and drop-safe await points. - Error triage and review: Diagnose UniFFI macro and bindgen failures (UniFfiTag, Lift/Lower bounds, UnexpectedUniFFICallbackError) with a symptom-cause-fix table, plus a 19-item merge checklist. - Use Case: When adding a new exported method to a Rust engine crate consumed by an Android and iOS app, use this Skill to choose the right types, keep the surface panic-free, and verify both generated bindings compile from one build. ## Quick Start Ask the agent to review the UniFFI boundary crate's exported API for correctness before merging the change.

Frequently Asked Questions about uniffi-boundary

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I choose between uniffi::Object and uniffi::Record?▼

Use an Object for state and behavior such as engine handles, sessions, or connection pools; it crosses as an opaque reference-counted handle and must be Send + Sync. Use a Record for messages and data like requests or results; it becomes a Kotlin data class or Swift struct copied by value.

How do I implement a foreign callback trait in UniFFI?▼

Declare the trait with #[uniffi::export(foreign)], require Send + Sync, and give every method a Result return whose error type implements From<uniffi::UnexpectedUniFFICallbackError>. Take it as Arc<dyn Trait>, pass arguments by value, and keep the trait coarse with one on_progress method.

Why does my UniFFI export fail with 'cannot find type UniFfiTag'?▼

This E0425 error means uniffi::setup_scaffolding!() is missing or placed in a submodule. Call it exactly once at the top of the crate root lib.rs; calling it twice causes duplicate ffi symbol definitions.

Can I pass &[u8] arguments across the UniFFI boundary?▼

Yes, since UniFFI 0.32 a &[u8] argument avoids copying and becomes a direct java.nio.ByteBuffer in Kotlin and Data in Swift. It cannot be returned, used in async exports, or used in foreign-trait methods, and Kotlin callers must pass a direct buffer at position 0.

What happens when Rust code panics in a UniFFI export?▼

Kotlin receives an InternalException outside the declared error type, and a Swift non-throwing function ends the app with a fatal error. Every fallible export must return Result with a uniffi::Error type, and non-throwing exports must be panic-free by construction.

Does UniFFI support async exported functions?▼

Yes, but the future must be Send, and exports using Tokio resources need #[uniffi::export(async_runtime = "tokio")] or the first poll panics with no reactor running. Async primary constructors are rejected by Kotlin bindgen, so use a named async constructor instead.