Fix stores with vec index method and expose opaque writer types (#4684)
* Use a different indexing method for each data structure * add a get method for slices * Rename trait for clarity and simplicity --------- Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com>
This commit is contained in:
1 parent
8d26a5d22e
commit
ecec70f5e8
6 files changed
+74
-8
No files matched your search
@@ -1,3 +1,5 @@
|
||||
//! Additional utilities for `BTreeMap` stores.
|
||||
|
||||
use std::{borrow::Borrow, collections::BTreeMap, hash::Hash, iter::FusedIterator};
|
||||
|
||||
use crate::{store::Store, ReadStore};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//! Additional utilities for `HashMap` stores.
|
||||
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
collections::HashMap,
|
||||
|
||||
@@ -1,14 +1,54 @@
|
||||
//! Additional utilities for indexing into stores.
|
||||
|
||||
use std::{
|
||||
collections::{BTreeMap, HashMap},
|
||||
hash::Hash,
|
||||
ops::{self, Index, IndexMut},
|
||||
};
|
||||
|
||||
use crate::{store::Store, ReadStore};
|
||||
use crate::{scope::SelectorScope, store::Store, ReadStore};
|
||||
use dioxus_signals::{
|
||||
AnyStorage, BorrowError, BorrowMutError, ReadSignal, Readable, UnsyncStorage, Writable,
|
||||
WriteLock, WriteSignal,
|
||||
};
|
||||
|
||||
/// The way a data structure index into its children based on a key. The selector must use this indexing
|
||||
/// method consistently to ensure that the same key always maps to the same child.
|
||||
pub trait IndexSelector<Idx> {
|
||||
/// Given a selector and an index, scope the selector to the child at the given index.
|
||||
fn scope_selector<Lens>(selector: SelectorScope<Lens>, index: &Idx) -> SelectorScope<Lens>;
|
||||
}
|
||||
|
||||
impl<T> IndexSelector<usize> for Vec<T> {
|
||||
fn scope_selector<Lens>(selector: SelectorScope<Lens>, index: &usize) -> SelectorScope<Lens> {
|
||||
selector.child_unmapped(*index as _)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IndexSelector<usize> for [T] {
|
||||
fn scope_selector<Lens>(selector: SelectorScope<Lens>, index: &usize) -> SelectorScope<Lens> {
|
||||
selector.child_unmapped(*index as _)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, I> IndexSelector<I> for HashMap<K, V>
|
||||
where
|
||||
I: Hash,
|
||||
{
|
||||
fn scope_selector<Lens>(selector: SelectorScope<Lens>, index: &I) -> SelectorScope<Lens> {
|
||||
selector.hash_child_unmapped(&index)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, I> IndexSelector<I> for BTreeMap<K, V>
|
||||
where
|
||||
I: Hash,
|
||||
{
|
||||
fn scope_selector<Lens>(selector: SelectorScope<Lens>, index: &I) -> SelectorScope<Lens> {
|
||||
selector.hash_child_unmapped(&index)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Lens, T> Store<T, Lens> {
|
||||
/// Index into the store, returning a store that allows access to the item at the given index. The
|
||||
/// new store will only update when the item at the index changes.
|
||||
@@ -23,12 +63,10 @@ impl<Lens, T> Store<T, Lens> {
|
||||
/// ```
|
||||
pub fn index<Idx>(self, index: Idx) -> Store<T::Output, IndexWrite<Idx, Lens>>
|
||||
where
|
||||
T: IndexMut<Idx> + 'static,
|
||||
Idx: Hash + 'static,
|
||||
T: IndexMut<Idx> + 'static + IndexSelector<Idx>,
|
||||
Lens: Readable<Target = T> + 'static,
|
||||
{
|
||||
self.into_selector()
|
||||
.hash_child_unmapped(&index)
|
||||
T::scope_selector(self.into_selector(), &index)
|
||||
.map_writer(move |write| IndexWrite { index, write })
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
mod btreemap;
|
||||
pub mod btreemap;
|
||||
mod deref;
|
||||
mod hashmap;
|
||||
mod index;
|
||||
pub mod hashmap;
|
||||
pub mod index;
|
||||
mod option;
|
||||
mod result;
|
||||
mod slice;
|
||||
|
||||
@@ -57,4 +57,27 @@ where
|
||||
{
|
||||
(0..self.len()).map(move |i| self.clone().index(i))
|
||||
}
|
||||
|
||||
/// Try to get an item from slice. This will only track the shallow state of the slice.
|
||||
/// It will only cause a re-run if the length of the slice could change. The new store
|
||||
/// will only update when the item at the index changes.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust, no_run
|
||||
/// use dioxus_stores::*;
|
||||
/// let store = use_store(|| vec![1, 2, 3]);
|
||||
/// let indexed_store = store.get(1).unwrap();
|
||||
/// // The indexed store can access the store methods of the indexed store.
|
||||
/// assert_eq!(indexed_store(), 2);
|
||||
/// ```
|
||||
pub fn get(&self, index: usize) -> Option<Store<I, IndexWrite<usize, Lens>>>
|
||||
where
|
||||
Lens: Clone,
|
||||
{
|
||||
if index >= self.len() {
|
||||
None
|
||||
} else {
|
||||
Some(self.clone().index(index))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
mod impls;
|
||||
mod store;
|
||||
mod subscriptions;
|
||||
pub use impls::*;
|
||||
pub use store::*;
|
||||
pub mod scope;
|
||||
|
||||
|
||||
Reference in new issue
Block a user