chinedufn / swift-bridge

swift-bridge facilitates Rust and Swift interop.
https://chinedufn.github.io/swift-bridge
Apache License 2.0
842 stars 62 forks source link

Suggestions for handling Arc<String> associated with enum #286

Closed jessegrosjean closed 2 months ago

jessegrosjean commented 3 months ago

Thanks for swift-bridge, it's really helping me out.

Can someone suggest how I can best handle an associated enum value of Arc<String>?

// Native rust value
pub enum Value {
    Bool(bool),
    Double(f64),
    String(Arc<String>)
}

#[swift_bridge::bridge]
mod ffi {
    // FFI representation
    pub enum ValueFFI {
        Bool(bool),
        Double(f64),
        String(Arc<String>),     <----- Problem case
    }
}

When I add String(Arc<String>) to the above FFI representation the swift-bridge macro crashes. I guess I need to wrap/hide that type somehow, but I can't see to find the right approach. Ideally I want to keep the Arc semantics, I don't want to just make and return a copy of the string.

Thanks for any tips.

jessegrosjean commented 3 months ago

I have managed to get it working by wrapping Arc<String> in a new ArcStringFFF type:

// Native rust value
pub enum Value {
    Bool(bool),
    Double(f64),
    String(Arc<String>)
}

#[swift_bridge::bridge]
mod ffi {
    // FFI representation
    pub enum ValueFFI {
        Bool(bool),
        Double(f64),
        String(ArcString),
    }

    extern "Rust" {
        type ArcStringFFI;

        #[swift_bridge(init)]
        fn new(string: &str) -> ArcStringFFI;
        fn to_string(&self) -> String;
    }
}

pub struct ArcStringFFI {
    inner: Arc<String>
}

impl ArcStringFFI {
    fn new(string: &str) -> Self {
        ArcStringFFI {
            inner: Arc::new(string.into())
        }
    }
    fn to_string(&self) -> String {
        self.inner.to_string()
    }
}

Is that correct? Is there an easier, less verbose or faster way? I have a number of other Arc<T> cases that I would also like to support.

Thanks.

chinedufn commented 2 months ago

Glad to hear you're finding swift-bridge helpful.


We haven't yet implemented support for Arc<T>.

We support Vec<T>, so we know how to bridge stdlib generic types, it's just a matter of doing it.


So, there current'y isn't an easier way than your approach.