#swift #ffi #bindings #ios #mac

swift-bridge-ir

Holds the data structures and logic for bridge module parsing and code generation

35 releases

Uses new Rust 2021

0.1.34 Jun 6, 2022
0.1.33 May 10, 2022
0.1.32 Apr 24, 2022
0.1.29 Mar 12, 2022
0.1.5 Nov 26, 2021

#8 in macOS and iOS APIs

Download history 102/week @ 2022-03-15 105/week @ 2022-03-22 75/week @ 2022-03-29 86/week @ 2022-04-05 75/week @ 2022-04-12 206/week @ 2022-04-19 388/week @ 2022-04-26 374/week @ 2022-05-03 598/week @ 2022-05-10 117/week @ 2022-05-17 314/week @ 2022-05-24 350/week @ 2022-05-31 244/week @ 2022-06-07 227/week @ 2022-06-14 183/week @ 2022-06-21 215/week @ 2022-06-28

931 downloads per month
Used in 4 crates (2 directly)

Apache-2.0/MIT

555KB
14K SLoC

swift-bridge Actions Status docs crates.io

swift-bridge facilitates Rust and Swift interop.

swift-bridge is a library that lets you pass and share high-level types such as Option<T>, String, Structs and Classes between Rust and Swift.

It also lets you bridge higher level language features between Rust and Swift, such as async functions and generics.

Installation

# In your Cargo.toml

[build-dependencies]
swift-bridge-build = "0.1"

[dependencies]
swift-bridge = "0.1"

Book

You can find information about using Rust and Swift together in The swift-bridge Book.

Quick Peek

You use swift-bridge by declaring the types and functions that you want to import and export in a "bridge module", and then annotating that bridge module with the #[swift_bridge::bridge] macro.

Then, at build time, you use either the swift-bridge-build API or the swift-bridge-cli CLI to parse your annotated bridge modules and generate the Swift and C side of the FFI layer.

Here's a quick peek at how you might describe an FFI boundary between Swift and Rust using a bridge module.

// Use the `swift_bridge::bridge` macro to declare a bridge module that
// `swift-bridge-build` will parse at build time in order to generate
// the necessary Swift and C FFI glue code.
#[swift_bridge::bridge]
mod ffi {
    // Create shared structs where both Rust and Swift can directly access the fields.
    struct AppConfig {
        file_manager: CustomFileManager,
    }

    // Shared enums are also supported
    enum UserLookup {
        ById(UserId),
        ByName(String),
    }

    // Export Rust types, functions and methods for Swift to use.
    extern "Rust" {
        type RustApp;

        #[swift_bridge(init)]
        fn new(config: AppConfig);
        
        fn insert_user(&mut self, user_id: UserId, user: User);
        fn get_user(&self, lookup: UserLookup) -> Option<&User>;
    }

    extern "Rust" {
        type User;

        #[swift_bridge(Copy(4))]
        type UserId;

        #[swift_bridge(init)]
        fn new(user_id: UserId, name: String, email: Option<String>) -> User;
    }

    // Import Swift classes and functions for Rust to use.
    extern "Swift" {
        type CustomFileManager;
        fn save_file(&self, name: &str, contents: &[u8]);
    }
}

#[derive(Copy)]
struct UserId(u32);

Quick Start

The swift-bridge repository contains example applications that you use to quickly try out the library, or as a starting point for your own Swift + Rust based application.

For example, here's how to run the codegen-visualizer example project locally.

git clone https://github.com/chinedufn/swift-bridge
cd swift-bridge/examples/codegen-visualizer

open CodegenVisualizer/CodegenVisualizer.xcodeproj
# *** Click the "Run" button at the top left of Xcode ***

You can find information about using Rust and Swift together in The swift-bridge Book.

Built-In Types

In addition to allowing you to share your own custom structs, enums and classes between Rust and Swift, swift-bridge comes with support for a number of Rust and Swift standard library types.

name in Rust name in Swift notes
u8, i8, u16, i16... etc UInt8, Int8, UInt16, Int16 ... etc
bool Bool
String, &String, &mut String RustString, RustStringRef, RustStringRefMut
&str RustStr
Vec<T> RustVec<T>
SwiftArray<T> Array<T> Not yet implemented
&[T] Not yet implemented
&mut [T] Not yet implemented
Box Not yet implemented
[T; N] Not yet implemented
*const T UnsafePointer<T>
*mut T UnsafeMutablePointer<T>
Option<T> Optional<T>
Result<T> Not yet implemented
Have a Rust standard library type in mind?
Open an issue!
Have a Swift standard library type in mind?
Open an issue!

To Test

To run the test suite.

# Clone the repository
git clone git@github.com:chinedufn/swift-bridge.git
cd swift-bridge

# Run tests
cargo test --all && ./test-integration.sh

License

Licensed under MIT or Apache-2.0.

Dependencies

~240–650KB
~16K SLoC