Added for_each_subsequent

Refs #156

The ForEach trait currently doesn't have a subsequent version, but given
the discussion in the related issue I think that's OK.
This commit is contained in:
Jonathan Johnson 2024-06-07 09:08:14 -07:00
parent 8c8dca63ba
commit 7bd13e2a0a
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
2 changed files with 93 additions and 21 deletions

View file

@ -9,10 +9,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Breaking Changes
- `Source::for_each_*` now invoke the callback with the current contents of of
the source before attaching the callback. New functions beginning with
`for_each_subsequent_` have been added with the original behavior.
### Fixed
- Fixed a panic that could occur when removing certain nested hierarchies from a
window.
- `CallbackHandle` now has a `must_use` hint that might help users discover the
persist function.
### Added

View file

@ -132,19 +132,83 @@ pub trait Source<T> {
}
/// Attaches `for_each` to this value so that it is invoked each time the
/// value's contents are updated.
/// source's contents are updated.
///
/// `for_each` will not be invoked with the currently stored value.
///
/// Returning `Err(CallbackDisconnected)` will prevent the callback from
/// being invoked again.
fn for_each_generational_try<F>(&self, for_each: F) -> CallbackHandle
fn for_each_subsequent_generational_try<F>(&self, for_each: F) -> CallbackHandle
where
T: Send + 'static,
F: for<'a> FnMut(DynamicGuard<'_, T, true>) -> Result<(), CallbackDisconnected>
+ Send
+ 'static;
/// Attaches `for_each` to this value and its [`Generation`] so that it is
/// invoked each time the value's contents are updated.
/// Attaches `for_each` to this value so that it is invoked each time the
/// source's contents are updated.
///
/// `for_each` will not be invoked with the currently stored value.
fn for_each_subsequent_generational<F>(&self, mut for_each: F) -> CallbackHandle
where
T: Send + 'static,
F: for<'a> FnMut(DynamicGuard<'_, T, true>) + Send + 'static,
{
self.for_each_subsequent_generational_try(move |value| {
for_each(value);
Ok(())
})
}
/// Attaches `for_each` to this value so that it is invoked each time the
/// source's contents are updated.
///
/// `for_each` will not be invoked with the currently stored value.
///
/// Returning `Err(CallbackDisconnected)` will prevent the callback from
/// being invoked again.
fn for_each_subsequent_try<F>(&self, mut for_each: F) -> CallbackHandle
where
T: Send + 'static,
F: for<'a> FnMut(&'a T) -> Result<(), CallbackDisconnected> + Send + 'static,
{
self.for_each_subsequent_generational_try(move |gen| for_each(&*gen))
}
/// Attaches `for_each` to this value so that it is invoked each time the
/// source's contents are updated.
///
/// `for_each` will not be invoked with the currently stored value.
fn for_each_subsequent<F>(&self, mut for_each: F) -> CallbackHandle
where
T: Send + 'static,
F: for<'a> FnMut(&'a T) + Send + 'static,
{
self.for_each_subsequent_try(move |value| {
for_each(value);
Ok(())
})
}
/// Invokes `for_each` with the current contents and each time this source's
/// contents are updated.
///
/// Returning `Err(CallbackDisconnected)` will prevent the callback from
/// being invoked again.
fn for_each_generational_try<F>(&self, mut for_each: F) -> CallbackHandle
where
T: Send + 'static,
F: for<'a> FnMut(DynamicGuard<'_, T, true>) -> Result<(), CallbackDisconnected>
+ Send
+ 'static,
{
self.map_generational(&mut for_each)
.expect("initial for_each invocation failed");
self.for_each_subsequent_generational_try(for_each)
}
/// Invokes `for_each` with the current contents and each time this source's
/// contents are updated.
fn for_each_generational<F>(&self, mut for_each: F) -> CallbackHandle
where
T: Send + 'static,
@ -156,8 +220,8 @@ pub trait Source<T> {
})
}
/// Attaches `for_each` to this value so that it is invoked each time the
/// value's contents are updated.
/// Invokes `for_each` with the current contents and each time this source's
/// contents are updated.
///
/// Returning `Err(CallbackDisconnected)` will prevent the callback from
/// being invoked again.
@ -169,8 +233,8 @@ pub trait Source<T> {
self.for_each_generational_try(move |gen| for_each(&*gen))
}
/// Attaches `for_each` to this value so that it is invoked each time the
/// value's contents are updated.
/// Invokes `for_each` with the current contents and each time this source's
/// contents are updated.
fn for_each<F>(&self, mut for_each: F) -> CallbackHandle
where
T: Send + 'static,
@ -182,8 +246,8 @@ pub trait Source<T> {
})
}
/// Attaches `for_each` to this value so that it is invoked each time the
/// value's contents are updated.
/// Invokes `for_each` with the current contents and each time this source's
/// contents are updated.
///
/// Returning `Err(CallbackDisconnected)` will prevent the callback from
/// being invoked again.
@ -192,8 +256,8 @@ pub trait Source<T> {
T: Clone + Send + 'static,
F: FnMut(GenerationalValue<T>) -> Result<(), CallbackDisconnected> + Send + 'static;
/// Attaches `for_each` to this value so that it is invoked each time the
/// value's contents are updated.
/// Invokes `for_each` with the current contents and each time this source's
/// contents are updated.
fn for_each_cloned_try<F>(&self, mut for_each: F) -> CallbackHandle
where
T: Clone + Send + 'static,
@ -202,8 +266,8 @@ pub trait Source<T> {
self.for_each_generational_cloned_try(move |gen| for_each(gen.value))
}
/// Attaches `for_each` to this value so that it is invoked each time the
/// value's contents are updated.
/// Invokes `for_each` with the current contents and each time this source's
/// contents are updated.
fn for_each_cloned<F>(&self, mut for_each: F) -> CallbackHandle
where
T: Clone + Send + 'static,
@ -531,7 +595,7 @@ impl<T> Source<T> for Arc<DynamicData<T>> {
}))
}
fn for_each_generational_try<F>(&self, mut for_each: F) -> CallbackHandle
fn for_each_subsequent_generational_try<F>(&self, mut for_each: F) -> CallbackHandle
where
T: Send + 'static,
F: for<'a> FnMut(DynamicGuard<'a, T, true>) -> Result<(), CallbackDisconnected>
@ -572,14 +636,14 @@ impl<T> Source<T> for Dynamic<T> {
self.0.try_map_generational(map)
}
fn for_each_generational_try<F>(&self, for_each: F) -> CallbackHandle
fn for_each_subsequent_generational_try<F>(&self, for_each: F) -> CallbackHandle
where
T: Send + 'static,
F: for<'a> FnMut(DynamicGuard<'_, T, true>) -> Result<(), CallbackDisconnected>
+ Send
+ 'static,
{
self.0.for_each_generational_try(for_each)
self.0.for_each_subsequent_generational_try(for_each)
}
fn for_each_generational_cloned_try<F>(&self, for_each: F) -> CallbackHandle
@ -602,14 +666,14 @@ impl<T> Source<T> for DynamicReader<T> {
})
}
fn for_each_generational_try<F>(&self, for_each: F) -> CallbackHandle
fn for_each_subsequent_generational_try<F>(&self, for_each: F) -> CallbackHandle
where
T: Send + 'static,
F: for<'a> FnMut(DynamicGuard<'_, T, true>) -> Result<(), CallbackDisconnected>
+ Send
+ 'static,
{
self.source.for_each_generational_try(for_each)
self.source.for_each_subsequent_generational_try(for_each)
}
fn for_each_generational_cloned_try<F>(&self, for_each: F) -> CallbackHandle
@ -749,7 +813,7 @@ impl<T> Source<T> for Owned<T> {
}))
}
fn for_each_generational_try<F>(&self, for_each: F) -> CallbackHandle
fn for_each_subsequent_generational_try<F>(&self, for_each: F) -> CallbackHandle
where
T: Send + 'static,
F: for<'a> FnMut(DynamicGuard<'a, T, true>) -> Result<(), CallbackDisconnected>
@ -1537,7 +1601,7 @@ trait CallbackCollection: Send + Sync + 'static {
///
/// To prevent the callback from ever being uninstalled, use
/// [`Self::persist()`].
#[must_use]
#[must_use = "Callbacks are disconnected once the associated CallbackHandle is dropped. Consider using `CallbackHandle::persist()` to prevent the callback from being disconnected."]
pub struct CallbackHandle(CallbackHandleInner);
impl Default for CallbackHandle {