Skip to content

Releases: chinedufn/swift-bridge

0.1.57

15 Aug 13:36
1b547a5
Compare
Choose a tag to compare
  • Support Failable initializers. #276 (thanks @NiwakaDev)

    // Rust
    
    #[swift_bridge::bridge]
    mod ffi {
        extern "Rust" {
            #[swift_bridge(Equatable)]
            type FailableInitType;
    
            #[swift_bridge(init)]
            fn new() -> Option<FailableInitType>;
        }
    }
    // Swift
    
    let failableInitType = FailableInitType()
    if failableInitType == nil {
        // ...
    } else {
       // ...
    }
  • Support Throwing initializers #287 (thanks @NiwakaDev)

    // Rust
    
    #[swift_bridge::bridge]
    mod ffi {
        enum ResultTransparentEnum {
            NamedField { data: i32 },
            UnnamedFields(u8, String),
            NoFields,
        }
        extern "Rust" {
            type ThrowingInitializer;
            #[swift_bridge(init)]
            fn new(succeed: bool) -> Result<ThrowingInitializer, ResultTransparentEnum>;
            fn val(&self) -> i32;
        }
    }
    // Swift
    
    do {
        let throwingInitializer = try ThrowingInitializer(false)
    } catch let error as ResultTransparentEnum {
        //...
    } catch {
        //...
    }

0.1.56

08 Aug 09:34
d2c09e2
Compare
Choose a tag to compare
  • Add swift-bridge parse-bridges CLI command. #274 (thanks @integer-overflown)

    swift-bridge-cli parse-bridges --crate-name my-crate -f src/lib.rs -o generated
    swift-bridge-cli parse-bridges --crate-name my-superb-crate \
      -f src/lib.rs \
      -f src/some_other_file.rs \
      -o generated
  • Respect bridge modules' visibility. #284 (thanks @jnbooth)

    // Notice that this is `pub mod`.
    // Before this commit `swift-bridge` would ignore the `pub` and instead
    // emit a `mod ffi`.
    // This made it impossible to `use enums::ffi_foo::MyEnum` from another module.
    #[swift_bridge::bridge]
    pub mod ffi_foo {
        enum MyEnum {
            VariantA,
            VariantB,
            VariantC,
        }
    }
    
    #[swift_bridge::bridge]
    pub(crate) mod ffi_bar {
        enum AnotherEnum {
            Variant1,
            Variant2,
        }
    }
  • Add a temporary work around for a dead code linting regression in Rust 1.79. #278 (thanks @sax)

    • rustc's dead code linting pass regressed in 1.79, causing swift-bridge to sometimes generate code that emitted dead code warnings, even though the code was not dead.
      // Some bridge modules that used `Result` were given an
      // "error: field `0` is never read" warning.
      #[swift_bridge::bridge]
      mod ffi {
          #[swift_bridge(swift_repr = "struct")]
          struct TransparentErrorStruct(pub String);
      
          extern "Rust" {
              fn rust_func_returns_result_transparent_struct(
                  succeed: bool
              ) -> Result<(), TransparentErrorStruct>;
          }
      }

0.1.55

29 Apr 03:20
87dbea3
Compare
Choose a tag to compare
  • Fix memory leak when passing Option<SwiftType> from Swift to Rust. #273
    • It is very unlikely that users were impacted by this leak Option<SwiftType> support was introduced about 10 hours ago
    • Full explanation of the leak can be found in 87dbea3
    #[swift_bridge::bridge]
    mod ffi {
        extern "Swift" {
            type SomeSwiftType;
        }
    
        extern "Rust" {
            // Calling with would leak memory in "0.1.54".
            // This no longer leaks as of "0.1.55".
            fn option_arg(arg: Option<SomeSwiftType>);
        }
    }

0.1.54

28 Apr 17:52
9d02d8f
Compare
Choose a tag to compare
  • Add support for bridging Option<SwiftType> in Rust function arguments and returns. #272 (thanks @Bright-Shard)
    #[swift_bridge::bridge]
    mod ffi {
        extern "Swift" {
            type SomeSwiftType;
        }
    
        extern "Rust" {
            fn option_arg(arg: Option<SomeSwiftType>);
            fn returns_option() -> Option<SomeSwiftType>;
        }
    }

0.1.53

26 Mar 00:39
04e6abf
Compare
Choose a tag to compare
  • Add support for bridging Option<&OpaqueRustType> in extern "Rust" modules. #257 (thanks @PrismaPhonic)

    #[swift_bridge::bridge]
    mod ffi {
      extern "Rust" {
        type MyRustType;
    
        fn my_func(arg: Option<&MyRustType>) -> Option<&MyRustType>;
      }
    }
  • Add support for bridging Option<String> in extern "Swift" args/returns and Option<&str> in extern "Swift" args. #264

    #[swift_bridge::bridge]
    mod ffi {
        extern "Swift" {
            fn opt_string_function(arg: Option<String>) -> Option<String>;
    
            fn opt_str_function(arg: Option<&str>);
        }
    }
  • Improve error message when reporting an unsupported attribute #244 (thanks @bes)

0.1.52

10 Jul 12:14
2724644
Compare
Choose a tag to compare
  • Improve support for order independent declarations. #230 (thanks @NiwakaDev)

  • Support Vec<PRIMITIVE> in Swift function argument and return types. #229 (thanks @timwedde)

     // Rust
    
     fn main() {
         let bytes = ffi::receive_bytes();
         println!("bytes: {:?}", bytes);
     
         let vec: Vec<u8> = vec![6, 1, 2, 3, 4, 5];
         ffi::send_bytes(vec);
     }
     
     #[swift_bridge::bridge]
     mod ffi {
         extern "Swift" {
             fn receive_bytes() -> Vec<u8>;
             fn send_bytes(vec: Vec<u8>);
         }
     }
     // Swift
    
     func send_bytes(vec: RustVec<UInt8>) {
         print("Received \(vec.len()) bytes from Rust")
         for val in vec {
             print(val)
         }
     }
     
     func receive_bytes() -> RustVec<UInt8> {
         let vec = RustVec<UInt8>()
         for i in 0 ... 4 {
             vec.push(value: UInt8(i))
         }
         return vec
     }
  • Support using already_declared enums and structs as Swift arguments. #226 (thanks @conectado)

    // For example, the following is now possible:
    
    #[swift_bridge::bridge]
    mod ffi_i {
      enum Animal {
        Alligator,
        Cat,
      }
    }
    
    use ffi_i::Foo;
    
    #[swift_bridge::bridge]
    mod ffi {
      #[swift_bridge(already_declared)]
      enum Animal {}
    
      extern "Swift" {
        fn hug(a: Animal);
      }
    }
  • Support Rust async fn return Result<(), enum>. #189 (thanks @NiwakaDev)

    // Rust
    #[swift_bridge::bridge]
    mod ffi {
        enum SomeEnum {
           //...
        }
        extern "Rust" {
            async fn some_function() -> Result<(), SomeEnum>;
        }
    }
    // Swift
    do {
        let value = try await some_function()
        //...
    } catch let error as SomeEnum {
        //...
    } catch {
        //...
    }
  • Support Rust async fn return Result<enum, enum>. #182 (thanks @NiwakaDev)

    // Rust
    
    #[swift_bridge::bridge]
    mod ffi {
        enum NetworkError {
            NoData,
            Authentication,
        }
        extern "Rust" {
            type Data;
        }
        extern "Rust" {
            async fn fetch_from_server() -> Result<Data, NetworkError>;
        }
    }
    // Swift
    
    do {
        let data = try await fetch_from_server()
        //...
    } catch let error as NetworkError {
        //...
    } catch {
        //...
    }
  • Fix and test async Rust fn return Result<(), OpaqueType>. #221 (thanks @jfaust)

  • Fix and test async Rust fn return Result<Vec<T>, *>. #218 (thanks @jfaust)

  • Support passing primitive tuples from Rust -> Swift. #195 (thanks @NiwakaDev)

    // Rust
    
    #[swift_bridge::bridge]
    mod ffi {
        extern "Rust" {
            fn reflect_tuple_primitives(tuple: (i16, u32)) -> (i16, u32);
        }
    }
    
    fn reflect_tuple_primitives(tuple: (i16, u32)) -> (i16, u32) {
        tuple
    }
    // Swift
    
    let tuple = reflect_tuple_primitives((-1, 10))
  • Support passing primitive tuples from Swift -> Rust. #205 + #211 (thanks @NiwakaDev)

    // Rust
    
    #[swift_bridge::bridge]
    mod ffi {
        extern "Swift" {
            fn swift_reflect_tuple_primitives(arg: (i32, u32)) -> (i32, u32);
        }
    }
    // Swift
    
    let tuple = swift_reflect_tuple_primitives((-123, 123));
  • Support returning Result<Tuple, *> from Rust to Swift. #213 (thanks @NiwakaDev)

    // Rust
    
    #[swift_bridge::bridge]
    mod ffi {
        extern "Rust" {
            fn rust_func_return_result_tuple_transparent_enum(
                succeed: bool,
            ) -> Result<(i32, ResultTestOpaqueRustType, String), ResultTransparentEnum>;
        }
    }
    // Swift
    
    do {
        //...
        let tuple: (Int32, ResultTestOpaqueRustType, RustString) = try rust_func_return_result_tuple_transparent_enum(true)
        //...
    } catch {
        //...
    }
  • Add RustVec<T>.as_ptr method #216 (thanks @aiongg)

  • Support #[derive(Debug)] on transparent enums. #194 (thanks @naturecodevoid)

    // Rust
    
    #[swift_bridge::bridge]
    mod ffi {
        #[derive(Debug)]
        enum DeriveDebugEnum {
            Variant,
        }
    }
    // Swift
    
    let debugString = String(reflecting: DeriveDebugEnum.Variant)
    XCTAssertEqual(debugString, "Variant")
  • Only support the #[swift_bridge(associated_to)] attribute on instance methods. #206 (thanks @NiwakaDev)

  • Support Option in Swift fns. #203

    mod ffi {
        extern "Swift" {
            fn my_func(arg: Option<u8>) -> Option<bool>;
        }
    }
  • Add Vec<f32> and Vec<f64> support. #200 (thanks @rkreutz)

    #[swift_bridge::bridge]
    mod ffi {
        #[swift_bridge(swift_repr = "struct")]
        struct SomeStruct {
            field: Vec<f32>,
        }
    
        extern "Rust" {
            fn do_something(val: SomeStruct) -> Vec<f32>;
        }
    }
    
    fn do_something(val: SomeStruct) -> Vec<f32> {
        // ...
    }
  • Add #[derive(Copy, Clone)] support to transparent structs. #198 (thanks @rkreutz)

    #[swift_bridge::bridge]
    mod ffi {
        #[swift_bridge(swift_repr = "struct")]
        #[derive(Copy, Clone)]
        struct Foo {
            field: u8,
        }
    }
  • Slightly simplify generated code for returning Result<(), OpaqueType>. #184 (thanks @NiwakaDev)

  • Support RustString in extern Swift functions. [#225] (thanks @NiwakaDev)

    // Swift
    func reflect_swift_string(arg: RustString) -> RustString {
        arg
    }
    // Rust
    #[swift_bridge::bridge]
    mod ffi {
        extern "Swift" {
            fn reflect_swift_string(arg: String) -> String;
        }
    }
    
    let foo = "foo";
    let string = ffi::reflect_swift_string(foo.to_string());
    assert_eq!(string.len(), 3);
    assert_eq!(&string, foo);

0.1.51

28 Feb 01:13
832498a
Compare
Choose a tag to compare
  • Support returning Result<(), OpaqueRustType> from Rust functions. #180 (thanks @jfaust)

    // For example, the following is now possible:
    
    #[swift_bridge::bridge]
    mod ffi {
        struct UnitStruct;
    
        extern "Rust" {
            type OpaqueType;
    
            fn null_result() -> Result<(), OpaqueType>;
            fn unit_result() -> Result<UnitStruct, OpaqueType>;
        }
    }
    
    fn null_result() -> Result<(), OpaqueType> {
        Ok(())
    }
    
    fn unit_result() -> Result<UnitStruct, OpaqueType> {
        Ok(UnitStruct)
    }
  • Support shared enums with named data. #175 (thanks @NiwakaDev)

    // For example, the following is now possible:
    
    #[swift_bridge::bridge]
    mod ffi {
        enum EnumWithNamedData {
            Variant1 { hello: String, data_u8: u8 },
            Variant2 { data_i32: i32 },
            Variant3 { foo: Foo },
        }
    
        extern "Rust" {
            #[swift_bridge(Equatable)]
            type Foo;
    
            #[swift_bridge(init)]
            fn new() -> Foo;
    
            fn reflect_enum_with_named_data(arg: EnumWithNamedData) -> EnumWithNamedData;
        }
    }
    // Swift
    
    let enumWithNamedData3 = EnumWithNamedData.Variant3(foo: Foo())
    switch reflect_enum_with_named_data(enumWithNamedData3) {
    case .Variant3(let foo):
        XCTAssertEqual(foo, Foo())
        break
    default:
        XCTFail()
    }
  • Support opaque types inside of data-carrying enums. #181 (thanks @NiwakaDev)

    // For example, the following is now possible:
    
    #[swift_bridge::bridge]
    mod ffi {
        enum OpaqueRustEnum {
            Unnamed(MyType)
            Named { field: MyType },
        }
    
        extern "Rust" {
            #[swift_bridge(Equatable)]
            type MyType;
    
            #[swift_bridge(init)]
            fn new() -> MyType;
    
            fn reflect_enum(arg: OpaqueRustEnum) -> OpaqueRustEnum;
        }
    }
    // Swift
    
    let opaqueRustEnum = OpaqueRustEnum.Named(field: MyType())
    
    switch reflect_enum(opaqueRustEnum) {
        case .Named(let named):
            XCTAssertEqual(named, MyType())
            break
        default:
            XCTFail()
    }
  • Reduce the FFI representation of ZSTs (zero-sized types) from one byte to zero bytes. #178

    • Previously ZSTs were bridged as a u8 in order to preserve FFI safety.
    • Now we simply inline the ZST on both sides of the FFI boundary, enabling zero memory overhead sharing of ZSTs.
    // For example, the following bridge module:
    
    #[swift_bridge::bridge]
    mod ffi {
        struct UnitStruct1;
        struct UnitStruct2{}
        struct UnitStruct3();
    
        extern "Rust" {
            fn some_function(
                arg1: UnitStruct1,
                arg2: UnitStruct2,
                arg3: UnitStruct3,
            ) -> UnitStruct1;
        }
    }
    // generates the following exported Rust function:
    
    #[link_name = "__swift_bridge__$some_function"]
    pub extern "C" fn __swift_bridge__some_function() {
        {super::some_function(UnitStruct1, UnitStruct2{}, UnitStruct3()); ()}
    }
    // and generates the following Swift:
    
    func some_function(arg1: UnitStruct1, arg2: UnitStruct2, arg3: UnitStruct3) -> UnitStruct1 {
        { let _ = __swift_bridge__$some_function(); UnitStruct1() }()
    }

0.1.50

20 Feb 18:06
8c7d1a3
Compare
Choose a tag to compare
  • Support data-carrying tuple enum variants. #172 (thanks @NiwakaDev)

    // For example, the following is now possible:
    
    #[swift_bridge::bridge]
    mod ffi {
        enum EnumWithUnnamedData {
            Variant1(String, u32),
            Variant2(i32, u8),
            Variant3,
        }
    }   
    // Swift
    
    let myEnum: EnumWithUnnamedData = .Variant2(10, 20)
  • Emit compile time errors when returning the wrong opaque Rust type. #169 (thanks @MikuroXina)

    // For example, the following will no longer compile:
    
    #[swift_bridge::bridge]
    mod ffi {
        extern "Rust" {
            // Before this release calling `get_reference()` from Swift would cause
            // undefined behavior.
            // As of this release this will no longer compile.
            fn get_reference() -> SomeType;
        }
    }
    
    // Note that the bridge module incorrectly declares `-> SomeType`
    // instead of `-> &'static SomeType`.
    fn get_reference() -> &'static SomeType {
        &SomeType
    }

0.1.49

09 Feb 12:28
d85c9b1
Compare
Choose a tag to compare
  • Support returning Result<OpaqueRust, OpaqueRust> from async Rust functions. #158 (thanks @NiwakaDev)

    // For example, the following is now possible:
    
    #[swift_bridge::bridge]
    mod ffi {
        extern "Rust" {
            type User;
            type ApiError;
    
            #[swift_bridge(swift_name = "loadUser")]
            async fn load_user() -> Result<User, ApiError>;
    
            fn print_info(self: &ApiError);
        }
    }
    // Swift
    
    do {
        let user = try await loadUser()
    } catch let err as ApiError {
        err.print_info()
    }
  • Introduce the #[swift_bridge(label = "...")] function argument attribute for generating Swift argument labels. #156 (thanks @NiwakaDev)

    // For example, the following is now possible:
    
    // Rust
    #[swift_bridge::bridge]
    mod ffi {
        extern "Rust" {
            fn add(
                #[swift_bridge(label = "leftHand")] 
                left_hand: i32,
                right_hand: i32,
            ) -> i32;
        }
    }
    
    fn add(left_hand: i32, right_hand: i32) -> i32 {
        left_hand + right_hand
    }
    // Swift
    
    let sum = add(leftHand: 10, 20)

0.1.48

29 Jan 19:37
5428646
Compare
Choose a tag to compare
  • Support returning Result<T, E> where T and E are opaque Rust types. #149

    // For example, the following is now possible:
    
    #[swift_bridge::bridge]
    mod ffi {
        extern "Rust" {
            type TypeA;
            type TypeB;
    
            fn some_function() -> Result<TypeA, TypeB>;
    
            fn print_info(self: &TypeB);
        }
    }
    // Swift
    
    do {
        let typeA = try some_function()
    } catch let typeB as TypeB {
        typeB.print_info()
    }
  • Support Option<Vec<T>> where T is a primitive type. #147 (thanks @NiwakaDev)

    // For example, the following is now possible:
    
    #[swift_bridge::bridge]
    mod ffi {
        extern "Rust" {
            fn some_function(arg: Option<Vec<u8>>) -> Option<Vec<i64>>;
        }
    }
  • Optimize RustStr's Swift Equatable protocol implementation. #151 (thanks @NiwakaDev)

  • Add compile time error messages for invalid args_into attributes. #145 (thanks @NiwakaDev)