Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ObservableVectorTransaction #32

Merged
merged 9 commits into from
Sep 7, 2023
Merged
4 changes: 0 additions & 4 deletions eyeball-im-util/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
//! Helpful utilities for [`eyeball-im`][eyeball_im].
//!
//! The primary entry point of this library is [`VectorExt`].

pub mod vector;

pub use vector::VectorExt;
130 changes: 88 additions & 42 deletions eyeball-im-util/src/vector.rs
Original file line number Diff line number Diff line change
@@ -1,51 +1,97 @@
//! Utilities around [`ObservableVector`].

use eyeball_im::{ObservableVector, Vector, VectorSubscriber};
//! Utilities around [`ObservableVector`][eyeball_im::ObservableVector].

mod filter;

use eyeball_im::VectorDiff;
use futures_core::Stream;

pub use self::filter::{Filter, FilterMap};

/// Extension trait for [`ObservableVector`].
pub trait VectorExt<T>
where
T: Clone + Send + Sync + 'static,
{
/// Obtain a new subscriber that filters items by the given filter function.
///
/// Returns a filtered version of the current vector, and a subscriber to
/// get updates through.
fn subscribe_filter<F>(&self, f: F) -> (Vector<T>, Filter<VectorSubscriber<T>, F>)
where
F: Fn(&T) -> bool;

/// Obtain a new subscriber that filters and maps items with the given
/// function.
///
/// Returns a filtered + mapped version of the current vector, and a
/// subscriber to get updates through.
fn subscribe_filter_map<U, F>(&self, f: F) -> (Vector<U>, FilterMap<VectorSubscriber<T>, F>)
where
U: Clone,
F: Fn(T) -> Option<U>;
}

impl<T> VectorExt<T> for ObservableVector<T>
where
T: Clone + Send + Sync + 'static,
{
fn subscribe_filter<F>(&self, f: F) -> (Vector<T>, Filter<VectorSubscriber<T>, F>)
where
F: Fn(&T) -> bool,
{
Filter::new((*self).clone(), self.subscribe(), f)
/// Abstraction over stream items that the adapters in this module can deal
/// with.
pub trait VectorDiffContainer: VectorDiffContainerOps<Self::Element> {
jplatte marked this conversation as resolved.
Show resolved Hide resolved
/// The element type of the [`Vector`][imbl::Vector] that diffs are being
/// handled for.
type Element;
}

impl<T> VectorDiffContainer for VectorDiff<T> {
type Element = T;
}

impl<T> VectorDiffContainer for Vec<VectorDiff<T>> {
type Element = T;
}

/// Type alias for extracting the element type from a stream of
/// [`VectorDiffContainer`]s.
pub type VectorDiffContainerStreamElement<S> =
<<S as Stream>::Item as VectorDiffContainer>::Element;

/// Type alias for extracting the [`VectorDiffContainerFamily`] type from a
/// stream of [`VectorDiffContainer`]s.
type VectorDiffContainerStreamFamily<S> =
<<S as Stream>::Item as VectorDiffContainerOps<VectorDiffContainerStreamElement<S>>>::Family;

/// Type alias for extracting the stream item type after the element type was
/// mapped to the given type `U`, from a stream of [`VectorDiffContainer`]s.
pub type VectorDiffContainerStreamMappedItem<S, U> =
<VectorDiffContainerStreamFamily<S> as VectorDiffContainerFamily>::Member<U>;

#[doc(hidden)]
pub trait VectorDiffContainerOps<T> {
type Family: VectorDiffContainerFamily;

fn filter_map<U>(
self,
f: impl FnMut(VectorDiff<T>) -> Option<VectorDiff<U>>,
) -> Option<<Self::Family as VectorDiffContainerFamily>::Member<U>>;
}

impl<T> VectorDiffContainerOps<T> for VectorDiff<T> {
type Family = VectorDiffFamily;

fn filter_map<U>(
self,
mut f: impl FnMut(VectorDiff<T>) -> Option<VectorDiff<U>>,
) -> Option<<Self::Family as VectorDiffContainerFamily>::Member<U>> {
f(self)
}
}

fn subscribe_filter_map<U, F>(&self, f: F) -> (Vector<U>, FilterMap<VectorSubscriber<T>, F>)
where
U: Clone,
F: Fn(T) -> Option<U>,
{
FilterMap::new((*self).clone(), self.subscribe(), f)
impl<T> VectorDiffContainerOps<T> for Vec<VectorDiff<T>> {
type Family = VecVectorDiffFamily;

fn filter_map<U>(
self,
f: impl FnMut(VectorDiff<T>) -> Option<VectorDiff<U>>,
) -> Option<<Self::Family as VectorDiffContainerFamily>::Member<U>> {
let res: Vec<_> = self.into_iter().filter_map(f).collect();
if res.is_empty() {
None
} else {
Some(res)
}
}
}

#[doc(hidden)]
pub trait VectorDiffContainerFamily {
type Member<T>: VectorDiffContainerOps<T, Family = Self>;
}

#[doc(hidden)]
#[derive(Debug)]
pub enum VectorDiffFamily {}

impl VectorDiffContainerFamily for VectorDiffFamily {
type Member<T> = VectorDiff<T>;
}

#[doc(hidden)]
#[derive(Debug)]
pub enum VecVectorDiffFamily {}

impl VectorDiffContainerFamily for VecVectorDiffFamily {
type Member<T> = Vec<VectorDiff<T>>;
}
Loading