This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: tauri-v2-mobile-ffi-direct-buffer-ownership

Tauri 2.0 Mobile Plugin FFI Direct Buffer Ownership & Lifetime Standard

Regulates memory ownership, lifecycle pinning, and deallocation boundaries for direct zero-copy byte buffers passed across Tauri 2.0 mobile FFI boundaries. Enforces explicit ownership transfer primitives and prevents cross-runtime deallocator mismatches between the Rust core and Swift/Kotlin host environments.

Prohibited Anti-Pattern: Cross-Runtime Double-Frees and Undefined Behavior via Implicit Foreign Buffer Deallocation

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Tauri 2.0 Mobile Plugin FFI Direct Buffer Ownership & Lifetime Standard - Regulates memory ownership, lifecycle pinning, and deallocation boundaries for direct zero-copy byte buffers passed across Tauri 2.0 mobile FFI boundaries. Enforces explicit ownership transfer primitives and prevents cross-runtime deallocator mismatches between the Rust core and Swift/Kotlin host environments.
globs: src-tauri/src/**/*.rs, plugins/**/src/**/*.rs, ios/**/*.swift, android/**/*.kt
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/tauri-v2-mobile-ffi-direct-buffer-ownership"
---

# Tauri 2.0 Mobile Plugin FFI Direct Buffer Ownership & Lifetime Standard

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Cross-Runtime Double-Frees and Undefined Behavior via Implicit Foreign Buffer Deallocation

## System Constraints
You are a Principal Engineer enforcing Tauri 2.0 Mobile Plugin FFI Direct Buffer Ownership Standard. Mandate explicit memory lifetimes, symmetric cross-runtime allocators/deallocators, pointer pinning against host garbage collectors, and total prevention of dangling pointers across Rust, Swift, and Kotlin mobile plugin boundaries.

## Strict Guidelines
- Engineers MUST ALWAYS deallocate memory using the exact allocator that created it; memory allocated by Rust's global allocator via `Vec` or `Box` MUST be freed through an exported Rust deallocator function, NEVER via Swift `free()` or JVM garbage collection.
- Engineers MUST NOT convert temporary references (`&[u8]`) into raw pointers for asynchronous FFI transfer across plugin boundaries; raw buffer pointers passed to mobile runtimes MUST originate from pinned, owned heap structures (`Vec::into_raw_parts` or `Box::into_raw`).
- Swift mobile wrappers MUST construct zero-copy `Data` buffers using `Data(bytesNoCopy:count:deallocator:.custom)` with a trailing closure that explicitly invokes the exported Rust FFI free symbol.
- Kotlin/JNI mobile wrappers MUST pin host memory or use `ByteBuffer.allocateDirect` when passing buffers into Rust; raw JNI addresses acquired via `GetDirectBufferAddress` MUST NOT be retained after the enclosing JNI scope without an explicit native global reference (`NewGlobalRef`).
- Services MUST validate buffer length (`len`) and capacity (`cap`) boundaries before dereferencing raw pointers in Rust to prevent buffer over-reads and out-of-bounds pointer arithmetic.

## Bad vs Good Implementations
### Rust to Swift Zero-Copy Buffer Ownership Transfer

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The Rust function returns a pointer to a vector that is dropped immediately at function exit, resulting in a use-after-free in Swift. Alternatively, if leaked with Box::leak, Swift freeing it via the system allocator corrupts heap metadata due to allocator mismatch.
```rust
// BAD: Leaking memory or creating a dangling pointer across the FFI boundary.
// The Vec is dropped at the end of the function, leaving Swift with a dangling pointer,
// or Swift attempts to free the buffer with the system free(), causing allocator mismatch.
#[no_mangle]
pub extern "C" fn plugin_capture_frame() -> *const u8 {
    let frame_data: Vec<u8> = vec![0xDE, 0xAD, 0xBE, 0xEF];
    // Dangling pointer: frame_data is deallocated right here!
    frame_data.as_ptr()
}

// Swift side assumed: free(ptr) -- fatal allocator mismatch crash on iOS
```

#### Production Standard (Correct)
> **Standard**: The FfiBuffer struct explicitly encodes pointer, length, and capacity. Rust uses mem::forget to transfer ownership across the FFI boundary. A dedicated export plugin_free_buffer reclaims ownership via Vec::from_raw_parts, allowing Swift to register a custom deallocator that ensures the originating allocator frees the memory.
```rust
// GOOD: Explicit C-compatible buffer struct with paired Rust deallocation export
#[repr(C)]
pub struct FfiBuffer {
    pub ptr: *mut u8,
    pub len: usize,
    pub cap: usize,
}

#[no_mangle]
pub extern "C" fn plugin_capture_frame() -> FfiBuffer {
    let mut data: Vec<u8> = vec![0xDE, 0xAD, 0xBE, 0xEF];
    let buffer = FfiBuffer {
        ptr: data.as_mut_ptr(),
        len: data.len(),
        cap: data.capacity(),
    };
    std::mem::forget(data); // Invariant: Rust relinquishes drop responsibility
    buffer
}

#[no_mangle]
pub unsafe extern "C" fn plugin_free_buffer(buffer: FfiBuffer) {
    if !buffer.ptr.is_null() && buffer.cap > 0 {
        // Reclaim ownership and drop via Rust's allocator
        drop(Vec::from_raw_parts(buffer.ptr, buffer.len, buffer.cap));
    }
}

// Swift consumption:
// let ffiBuffer = plugin_capture_frame()
// let data = Data(bytesNoCopy: ffiBuffer.ptr, count: ffiBuffer.len, deallocator: .custom { _, _ in
//     plugin_free_buffer(ffiBuffer)
// })
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Tauri 2.0 Mobile Plugin FFI Direct Buffer Ownership & Lifetime Standard

Tauri 2.0 Mobile Plugin FFI Direct Buffer Ownership & Lifetime Standard defines an industrial-grade behavioral standard for mobile engineering. Regulates memory ownership, lifecycle pinning, and deallocation boundaries for direct zero-copy byte buffers passed across Tauri 2.0 mobile FFI boundaries. Enforces explicit ownership transfer primitives and prevents cross-runtime deallocator mismatches between the Rust core and Swift/Kotlin host environments. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Cross-Runtime Double-Frees and Undefined Behavior via Implicit Foreign Buffer Deallocation Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftCross-Runtime Double-Frees and Undefined Behavior via Implicit Foreign Buffer DeallocationCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS deallocate memory using the exact allocator that created it

Engineers MUST ALWAYS deallocate memory using the exact allocator that created it; memory allocated by Rust's global allocator via `Vec` or `Box` MUST be freed through an exported Rust deallocator function, NEVER via Swift `free()` or JVM garbage collection.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NOT convert temporary references (`&[u8]`) into raw pointers for asynchronous FFI transfer across plugin boundaries

Engineers MUST NOT convert temporary references (`&[u8]`) into raw pointers for asynchronous FFI transfer across plugin boundaries; raw buffer pointers passed to mobile runtimes MUST originate from pinned, owned heap structures (`Vec::into_raw_parts` or `Box::into_raw`).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Swift mobile wrappers MUST construct zero-copy `Data` buffers using `Data(bytesNoCopy

Swift mobile wrappers MUST construct zero-copy `Data` buffers using `Data(bytesNoCopy:count:deallocator:.custom)` with a trailing closure that explicitly invokes the exported Rust FFI free symbol.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Kotlin/JNI mobile wrappers MUST pin host memory or use `ByteBuffer.allocateDirect` when passing buffers into Rust

Kotlin/JNI mobile wrappers MUST pin host memory or use `ByteBuffer.allocateDirect` when passing buffers into Rust; raw JNI addresses acquired via `GetDirectBufferAddress` MUST NOT be retained after the enclosing JNI scope without an explicit native global reference (`NewGlobalRef`).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Services MUST validate buffer length (`len`) and capacity (`cap`) boundaries before dereferencing raw pointers in Rust to prevent buffer over-reads and out-of-bounds pointer arithmetic.

Services MUST validate buffer length (`len`) and capacity (`cap`) boundaries before dereferencing raw pointers in Rust to prevent buffer over-reads and out-of-bounds pointer arithmetic.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Tauri 2.0 Mobile Plugin FFI Direct Buffer Ownership & Lifetime Standard critical for AI coding assistants?

Regulates memory ownership, lifecycle pinning, and deallocation boundaries for direct zero-copy byte buffers passed across Tauri 2.0 mobile FFI boundaries. Enforces explicit ownership transfer primitives and prevents cross-runtime deallocator mismatches between the Rust core and Swift/Kotlin host environments. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Cross-Runtime Double-Frees and Undefined Behavior via Implicit Foreign Buffer Deallocation) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

Related MOBILE Rules

View all rules →
1 Rule in Stack

Tauri