Builder pattern with uniffi
⚓ Rust 📅 2025-10-01 👤 surdeus 👁️ 7Trying to implement a builder pattern in Rust to be used in Swift with UniFFI but i found a sharp edge which is this one
A regular builder pattern would be like this:
pub struct MyThingBuilder {
    field1: Option<String>,
    field2: Option<u32>,
}
impl MyThingBuilder {
    pub fn new() -> Self {
        Self {
            field1: None,
            field2: None,
        }
    }
    pub fn field1(mut self, val: String) -> Self {
        self.field1 = Some(val);
        self
    }
    pub fn field2(mut self, val: u32) -> Self {
        self.field2 = Some(val);
        self
    }
    pub fn build(self) -> MyThing {
        MyThing {
            field1: self.field1.unwrap_or_default(),
            field2: self.field2.unwrap_or_default(),
        }
    }
}
But returning self each time seems to be incompatible with UniFFI. Therefor the solution i get from clankers is to write it like this:
    use std::sync::Arc;
    pub struct MyThing {
        pub field1: String,
        pub field2: u32,
    }
    
    pub struct MyThingBuilder {
        field1: Option<String>,
        field2: Option<u32>,
    }
    
    impl MyThingBuilder {
        pub fn new() -> Arc<Self> {
            Arc::new(Self {
                field1: None,
                field2: None,
            })
        }
    
        pub fn field1(self: Arc<Self>, val: String) -> Arc<Self> {
            let mut new = (*self).clone();
            new.field1 = Some(val);
            Arc::new(new)
        }
    
        pub fn field2(self: Arc<Self>, val: u32) -> Arc<Self> {
            let mut new = (*self).clone();
            new.field2 = Some(val);
            Arc::new(new)
        }
    
        pub fn build(self: Arc<Self>) -> MyThing {
            MyThing {
                field1: self.field1.clone().unwrap_or_default(),
                field2: self.field2.unwrap_or_default(),
            }
        }
    }
    impl Clone for MyThingBuilder {
        fn clone(&self) -> Self {
            Self {
                field1: self.field1.clone(),
                field2: self.field2,
            }
        }
    }
Is there a cleaner way of getting this working with UniFFI without cloning each time i return data per chaining? Am i missing something?
2 posts - 2 participants
🏷️ Rust_feed