pub trait PathExt: Path {
Show 14 methods
// Provided methods
fn borrow_opt(&self) -> Option<Ref<'_, <Self as Path>::Out>> { ... }
fn borrow_opt_mut(&self) -> Option<BorrowMutGuard<'_, Self>> { ... }
fn borrow_opt_mut_without_notifying(
&self,
) -> Option<RefMut<'_, <Self as Path>::Out>> { ... }
fn notify_changed(&self) { ... }
fn get_opt(&self) -> Option<Self::Out>
where Self::Out: Clone { ... }
fn set_opt(&self, data: Self::Out) -> Result<(), Self::Out>
where Self::Out: Sized { ... }
fn until_change(&self) -> UntilChange<'_> { ... }
fn signal_stream(&self, fire_immediately: bool) -> SignalStream<'_, Self> { ... }
fn for_each<C: FnMut(&Self::Out)>(&self, closure: C) -> ForEach<'_, Self, C> ⓘ { ... }
fn for_each_async<F: Future<Output = ()>, C: FnMut(&Self::Out) -> F>(
&self,
closure: C,
) -> ForEachAsync<'_, Self, F, C> { ... }
fn bind_for_each<C: FnMut(&Self::Out), I: Stream<Item = Self::Out>>(
&self,
on_change: C,
incoming_changes: I,
) -> BindForEach<'_, Self, C, I> ⓘ { ... }
fn until_bubbling_change(&self) -> UntilChange<'_> { ... }
fn build_path(self) -> <Self::Out as Trackable>::PathBuilder<Self>
where Self: Sized,
Self::Out: Trackable { ... }
fn as_ref_path(
&self,
) -> <Self::Out as Trackable>::PathBuilder<ReferencePath<'_, Self>>
where Self::Out: Trackable { ... }
}
Expand description
Provided Methods§
Sourcefn borrow_opt(&self) -> Option<Ref<'_, <Self as Path>::Out>>
fn borrow_opt(&self) -> Option<Ref<'_, <Self as Path>::Out>>
Borrow the data at this path immutably.
Returns None if the data identified by this path does not exist at the moment. For example…
- The path might point to data in an enum variant, but the enum might be in a different variant.
- The path might point to data associated with a specific key in a HashMap, but the HashMap might not have data at that key.
If there is an existing mutable borrow anywhere in the store, this method will panic.
See also: borrow - like this method, but for cases where we know None won’t be returned.
#[derive(Trackable)]
#[track(deep)]
enum MyEnum {
Variant1(i32),
Variant2(String)
}
let store = Store::new(MyEnum::Variant1(5));
let path_to_var1 = store.build_path().Variant1_0();
// Borrow the `i32` inside the first enum variant.
assert_eq!(path_to_var1.borrow_opt().as_deref(), Some(&5));
let path_to_var2 = store.build_path().Variant2_0();
// Can't borrow the `String`; the enum is in another variant.
assert!(path_to_var2.borrow_opt().is_none());
§Time Complexity
O(L) where L is the length of this path
Sourcefn borrow_opt_mut(&self) -> Option<BorrowMutGuard<'_, Self>>
fn borrow_opt_mut(&self) -> Option<BorrowMutGuard<'_, Self>>
Borrow the data at this path mutably, notifying all the relevant change listeners when the returned borrow guard is dropped.
Returns None if the data identified by this path does not exist at the moment. For example…
- The path might point to data in an enum variant, but the enum might be in a different variant.
- The path might point to data associated with a specific key in a HashMap, but the HashMap might not have data at that key.
If there is an existing mutable or immutable borrow anywhere in the store, this method will panic.
See also: borrow_mut - like this method, but for cases where we know None won’t be returned.
#[derive(Trackable)]
#[track(deep)]
enum MyEnum {
Variant1(i32),
Variant2(String)
}
let store = Store::new(MyEnum::Variant1(5));
let path_to_var1 = store.build_path().Variant1_0();
// The enum is in the first variant so we are sure we can borrow
// and mutate the `i32`.
*path_to_var1.borrow_opt_mut().unwrap() += 1;
assert_eq!(path_to_var1.borrow_opt().as_deref(), Some(&6));
let path_to_var2 = store.build_path().Variant2_0();
assert!(path_to_var2.borrow_opt_mut().is_none());
§Time Complexity
O(L + D_1 + D_2 + … + D_N) where L is the length of this path and D_i is the length of the path of the ith subscriber (N is the number of subscribers that will be woken by the mutation, not the total number of subscribers in the store)
Sourcefn borrow_opt_mut_without_notifying(
&self,
) -> Option<RefMut<'_, <Self as Path>::Out>>
fn borrow_opt_mut_without_notifying( &self, ) -> Option<RefMut<'_, <Self as Path>::Out>>
Borrow the data at this path mutably without notifying any listener.
Use this in conjunction with the notify_changed method.
Sourcefn notify_changed(&self)
fn notify_changed(&self)
Notify all listeners that the data at this location has changed.
This method is not needed when using borrow_opt_mut or borrow_mut; in those cases notifications are sent automatically.
This method is useful in the relatively rare situations when you need borrow_opt_mut_without_notifying.
§Time Complexity
Same as borrow_opt_mut.
Sourcefn get_opt(&self) -> Option<Self::Out>
fn get_opt(&self) -> Option<Self::Out>
Clone the data identified by this path.
Equivalent to path.borrow_opt().as_deref().map(Clone::clone)
.
Sourcefn set_opt(&self, data: Self::Out) -> Result<(), Self::Out>
fn set_opt(&self, data: Self::Out) -> Result<(), Self::Out>
Set the data identified by this path, notifying listeners.
If the data cannot be accessed, Err is returned with the input.
Sourcefn until_change(&self) -> UntilChange<'_>
fn until_change(&self) -> UntilChange<'_>
Get a Stream that fires everytime a mutable borrow is taken of this or any encompassing piece of data.
In other words, whenever someone call borrow_opt_mut
or borrow_mut on this path
(the same one you’re calling until_change
on) or any path that is a
prefix of this one, the stream will fire.
#[derive(Default, Trackable)]
struct MyStruct {
field_1: i32,
field_2: u64
}
let store = Store::new(MyStruct::default());
// path to the `MyStruct` itself
let path = store.build_path();
let stream = path.until_change();
path.borrow_opt_mut(); // will fire the stream
path.field_1().borrow_opt_mut(); // will fire the stream
path.field_2().borrow_opt_mut(); // won't fire the stream
§Stream Behavior
§Spurious Fires
The stream may fire spuriously, although the chance of this happening is extremely low.
§Batching
If multiple changes happen in quick succession (“quick succession” means in-between calls to Stream::poll_next, to be precise), the stream may only fire once.
This means the stream can be used for detecting changes, but not for counting how many changes happened.
§Time Complexity
On creation and each poll: O(L) where L is the length of this path
Sourcefn signal_stream(&self, fire_immediately: bool) -> SignalStream<'_, Self>
fn signal_stream(&self, fire_immediately: bool) -> SignalStream<'_, Self>
Get a Stream that fires once every time the data changes, yielding Refs to the data.
If the fire_immediately
argument is true
, then the stream will fire
on the first poll too.
The stream ends when the data cannot be borrowed (when borrow_opt returns None).
This stream is useful for linking the data to some side-effect. For example, you can sync a UI widget content with the data…
use futures_lite::StreamExt;
// set the text with the current data
// and update the text whenever the data change
path.signal_stream(true).for_each(|data: Ref<'_, String>| {
let s: &str = &**data;
ui_element.set_text(s);
}).await;
Note that if this is all you need, use for_each instead.
§Panic Opportunity
This method returns a Ref. It is ‼️extremely important‼️ that you
use the Ref and drop it as soon as possible. While the Ref is held,
any attempt to mutably borrow any data in the store will panic.
Holding the Ref for a long time (especially across a await
points)
is thus a very bad idea.
§Equivalent Behavior with Streams
This method is merely for convenience. You can achieve the same functionality yourself like so…
let stream = path.signal_stream(true);
// is equivalent to
let stream = futures_lite::stream::once(()) // fire immediately in the beginning...
.chain(path.until_change()) // and after every change
.map(|_| path.borrow_opt()) // borrow the data into a Ref
.take_while(Option::is_some) // end the stream if the data is unavailable
.map(Option::unwrap); // we've already checked that the data isn't none
Sourcefn for_each<C: FnMut(&Self::Out)>(&self, closure: C) -> ForEach<'_, Self, C> ⓘ
fn for_each<C: FnMut(&Self::Out)>(&self, closure: C) -> ForEach<'_, Self, C> ⓘ
Execute the given function with the data as argument. Repeat every time the data changes.
The return future never finishes.
// set the text with the current data
// and update the text whenever the data change
path.for_each(|s: &String| {
ui_element.set_text(s);
}).await;
This is a less powerful (and less panic-inducing) alternative to the signal_stream method.
Sourcefn for_each_async<F: Future<Output = ()>, C: FnMut(&Self::Out) -> F>(
&self,
closure: C,
) -> ForEachAsync<'_, Self, F, C>
fn for_each_async<F: Future<Output = ()>, C: FnMut(&Self::Out) -> F>( &self, closure: C, ) -> ForEachAsync<'_, Self, F, C>
Execute the given async function (a function returning Future) with the data as argument. Repeat every time the data changes.
If the async function is still executing when the data changes, the execution is canceled (by dropping the Future) so that the new one can start.
The return future never finishes.
// when the URL changes, fetch the content and set the text
path_to_url.for_each_async(|url: &String| {
let url = url.clone();
async move {
let content = fetch_content(&url).await;
ui_element.set_text(&content);
}
}).await;
Sourcefn bind_for_each<C: FnMut(&Self::Out), I: Stream<Item = Self::Out>>(
&self,
on_change: C,
incoming_changes: I,
) -> BindForEach<'_, Self, C, I> ⓘ
fn bind_for_each<C: FnMut(&Self::Out), I: Stream<Item = Self::Out>>( &self, on_change: C, incoming_changes: I, ) -> BindForEach<'_, Self, C, I> ⓘ
For making a two-way binding.
The given on_change
function is called once in the beginning and
whenever the data changes (just like with for_each).
Whenever the given incoming_changes
Stream yield a value,
the data will be updated to that value. The on_change
function
won’t be called for changes that come in this way.
The future finishes when the incoming_changes
stream yield None.
path.bind_for_each(
// set the text with the current data
// and update the text whenever the data change
|s: &String| {
text_field_widget.set_text(s);
},
// whenever the user type into the field, update the data
text_field_widget
.until_change()
.map(|_| text_field_widget.get_text())
).await;
Sourcefn until_bubbling_change(&self) -> UntilChange<'_>
fn until_bubbling_change(&self) -> UntilChange<'_>
Get a Stream that fires everytime a mutable borrow is taken of this piece of data or anything inside it.
In other words, whenever someone call borrow_opt_mut
or borrow_mut on this path
(the same one you’re calling until_bubbling_change
on) or any path that this
path is a prefix of, the stream will fire.
#[derive(Trackable)]
#[track(deep)]
struct MyStruct<T> {
field_1: T,
field_2: u64
}
let store = Store::new(MyStruct {
field_1: MyStruct {
field_1: String::new(),
field_2: 123
},
field_2: 456
});
// path to the root `MyStruct` itself.
let root = store.build_path();
// path to the `field_1` in the root `MyStruct`.
let listening = root.field_1();
let stream = listening.until_bubbling_change();
root.field_1().borrow_opt_mut(); // will fire the stream
root.field_1().field_1().borrow_opt_mut(); // will fire the stream
root.field_1().field_2().borrow_opt_mut(); // will fire the stream
root.borrow_opt_mut(); // won't fire the stream
root.field_2().borrow_opt_mut(); // won't fire the stream
§Stream Behavior
The returned stream may spuriously fire or batch changes. See until_change documentation.
§Time Complexity
On creation: O(L) where L is the length of this path
On each poll: O(1)
Sourcefn build_path(self) -> <Self::Out as Trackable>::PathBuilder<Self>
fn build_path(self) -> <Self::Out as Trackable>::PathBuilder<Self>
Gives a PathBuilder for creating a path that continues from this path.
This is useful when you are handling the type that implements Path
directly. Most of the time, though, you will already be working with
PathBuilder
s.
fn modify_string(path: impl Path<Out = String>) {
path.set_opt("haha".to_string()).ok();
}
#[derive(Trackable)]
struct MyStruct {
s: String
}
let store = Store::new(MyStruct {
s: String::from("hello world")
});
modify_string(store.build_path().s().into_path());
assert_eq!(&**store.build_path().s().borrow(), "haha");
Sourcefn as_ref_path(
&self,
) -> <Self::Out as Trackable>::PathBuilder<ReferencePath<'_, Self>>
fn as_ref_path( &self, ) -> <Self::Out as Trackable>::PathBuilder<ReferencePath<'_, Self>>
Create a new Path from borrowing this path.
let store = Store::new(MyStruct::default());
// `path_a` lives for as long as the store.
let path_a = store.build_path();
// `path_b` composes `path_a`.
// `path_b` lives for as long as the store.
let path_b = path_a.field_1();
// `path_c` borrows `path_a`.
// if you drop `path_a`, `path_c` will no longer be usable.
let path_c = path_a.as_ref_path().field_1();
Note that the new path will only live for as long as the borrow. This means it won’t be useful for use cases requiring long-lived path (such as implementing an undo-redo log).
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.