fzyzcjy / flutter_rust_bridge

Flutter/Dart <-> Rust binding generator, feature-rich, but seamless and simple.
https://fzyzcjy.github.io/flutter_rust_bridge/
MIT License
3.61k stars 254 forks source link

Improve Documentation about borrow types #1916

Open patmuk opened 2 weeks ago

patmuk commented 2 weeks ago

I am not totally sure, but I assume that a struct with borrowed fields is auto opaque?

If so, can this be stated better in the documentation, for others?

My use case is having a viewModel, but defined in Rust. Thus it needs to be read by flutter, so I can't use an opaque type. But being a viewModel, I want to use borrowed values from the Model ... so the only option left is cloning the model's fields on each access ... or implementing the view logic in Flutter. So either the performance is suboptimal, or the logic might be repeated for different UIs (Flutter, cli, ...).

For example, a model like

struct MyModel {
    items : Vec<Field>
}

could have the viewModel

struct MyViewModel {
    my_items : Vec<&Field>
    not_my_items : Vec<&Field>
    total_item_count : u64
}

This is all very theoretical - as the performance hit might be not noticeable and I might never have a second UI, as Flutter covers all platforms. But back to my request: It would be good to document this more clear if I understood it correctly.

fzyzcjy commented 2 weeks ago

a struct with borrowed fields is auto opaque?

By default IMHO; try to add #[frb(non_opaque)] and see whether it works.

IIRC this was originally non-opaque, but later it gives problems on some scenarios and thus the default is flipped and it looks like this...

patmuk commented 2 weeks ago

Thanks! But it doesn't seem to work: The lifetime parameter is missing in the generated code:

// Codec=Dco (DartCObject based), see doc to use other codecs
            impl flutter_rust_bridge::IntoDart for crate::domain::share_cycle::ShareCycleViewModel {
                fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
                    [
                    self.wanted_items.into_into_dart().into_dart(),
self.to_share_tems.into_into_dart().into_dart(),
self.completely_shared_items.into_into_dart().into_dart()
                ].into_dart()
                }
            }
            impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::domain::share_cycle::ShareCycleViewModel {}
impl flutter_rust_bridge::IntoIntoDart<crate::domain::share_cycle::ShareCycleViewModel> for crate::domain::share_cycle::ShareCycleViewModel {
            fn into_into_dart(self) -> crate::domain::share_cycle::ShareCycleViewModel {
                self
            }
        }

my struct is

#[flutter_rust_bridge::frb(non_opaque)]
#[derive(Debug, PartialEq, Eq)]
pub struct ShareCycleViewModel<'a> {
    pub wanted_items: Vec<&'a MediaItem>,
    pub to_share_tems: Vec<&'a MediaItem>,
    pub completely_shared_items: Vec<&'a MediaItem>,
}

Probably this was where the problem with non-opaque borrowed fields started?

fzyzcjy commented 2 weeks ago

Hmm, it looks like borrowed opaque types are not supported (at least yet). To work on it, maybe we can first discuss - what code should it generate? Unsafe code can definitely handle it, but I would like to have as little unsafe code as possible, surely ;)

patmuk commented 2 weeks ago

Yes, I agree - I would not like unsafe code as well. Honestly, I think it might not be worth the effort. Probably modifying a Model to be shown in a view is part of the view, not the core ... even if different views have to do the same. Or more general: If something in rust should be used by flutter (and not just passed through), it should be owned. Technically it might work - but I have the feeling that along the way one gets into trouble sooner or later.