thlorenz / rid

Rust integrated Dart framework providing an easy way to build Flutter apps with Rust.
64 stars 4 forks source link

Referencing state that lives outside the state tree #44

Closed SecondFlight closed 2 years ago

SecondFlight commented 2 years ago

This issue covers support for Rc and Arc.

Rationale

There may be reasons to reference a large piece of state outside of the state tree, and to keep it around even if it's not in the state tree.

One example of this is undo/redo via the command pattern. Let's say you have some message MsgThatCreatesAReallyLongString. When the message handler receives this message, it creates a command with a long string, which it allocates memory for, and then it executes the command. It would be nice to be able to use a Rc for this, as it would allow you to only allocate the memory once. As it stands, I think your only option is to clone the string from the command struct when creating the item in the Store.

Using a Rc in this case feels more correct to me than cloning, but I haven't run into a case where this ends up being performance-critical.

SecondFlight commented 2 years ago

I tried implementing this locally but I got stuck in Rust macro land. Conceptually it feels like it should be simple - any valid RustType should be able to be wrapped in an Rc and exposed identically in Dart, or at least so goes my reasoning. I'm not prepared to learn token parsing right now but I may attack this some other time.

SecondFlight commented 2 years ago

On second thought, my example may be completely misguided. I would expect a command to have immutable state, since I don't want its data to update as my state tree changes.

There may be other motivating use-cases for this, but I don't have any at the moment.

thlorenz commented 2 years ago

There may be reasons to reference a large piece of state outside of the state tree, and to keep it around even if it's not in the state tree.

I agree, so let's see how we can make that work. At this point the state is immutable and forces all parts of the app to go to that state via the store to treat it as the source of truth.

I understand that this requirements creates overhead that could otherwise be avoided and if the string is huge that'd be especially bad. However we need to think a possible implementation of this through very carefully. Let's use this issue to scheme this out.

BTW nothing is preventing you to do a prototype of this today without going into macro land as you could just use #[rid::skip] to avoid having to support RC type conversions to Dart. An example of this is in the reddit_ticker example. You then #[rid::export] to make this string accessible to Dart (instead of as a field).

#[rid::skip] is currently not documented as I'm behind with the docs ATM.

So let's start with a simple prototype app (in the worst case it doesn't have to compile) to hash out how this could work.

SecondFlight commented 2 years ago

Thanks for taking a look at this.

I think I'll hold off on creating an example until I can free up some brain cells to work through it. I don't think I have a good handle on the problem space yet, especially after reading your reply.

I fully expect to need to work through this at some point, so for now I'll rename the title to something that reflects the intent, and put a bookmark in my head for later.

thlorenz commented 2 years ago

I'll keep it labeled as feature request (saw after I added the label that you had removed it intentionally). We can remove it if you want, but I think it's a good idea to track those potential enhancements under this label.

SecondFlight commented 2 years ago

After some more experience with Rid as well as time to think about the problem, I think my initial rationale was flawed for a number of reasons, at least for my use-case.

I think I really want something that lives in my authoritative single-source-of-truth state tree in Rust, but that doesn't require Rid annotations and that is invisible to Rid bindgen.

So in other words, I'm looking for #[rid(skip)].

I'm going to close this for now, as #[rid(skip)] fits my needs. Please feel free to reopen and clarify if you have something else in mind.