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 std::{borrow::Borrow, collections::BTreeMap, hash::Hash, iter::FusedIterator};
|
||||||
|
|
||||||
use crate::{store::Store, ReadStore};
|
use crate::{store::Store, ReadStore};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
//! Additional utilities for `HashMap` stores.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Borrow,
|
borrow::Borrow,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
|||||||
@@ -1,14 +1,54 @@
|
|||||||
|
//! Additional utilities for indexing into stores.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
collections::{BTreeMap, HashMap},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
ops::{self, Index, IndexMut},
|
ops::{self, Index, IndexMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{store::Store, ReadStore};
|
use crate::{scope::SelectorScope, store::Store, ReadStore};
|
||||||
use dioxus_signals::{
|
use dioxus_signals::{
|
||||||
AnyStorage, BorrowError, BorrowMutError, ReadSignal, Readable, UnsyncStorage, Writable,
|
AnyStorage, BorrowError, BorrowMutError, ReadSignal, Readable, UnsyncStorage, Writable,
|
||||||
WriteLock, WriteSignal,
|
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> {
|
impl<Lens, T> Store<T, Lens> {
|
||||||
/// Index into the store, returning a store that allows access to the item at the given index. The
|
/// 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.
|
/// 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>>
|
pub fn index<Idx>(self, index: Idx) -> Store<T::Output, IndexWrite<Idx, Lens>>
|
||||||
where
|
where
|
||||||
T: IndexMut<Idx> + 'static,
|
T: IndexMut<Idx> + 'static + IndexSelector<Idx>,
|
||||||
Idx: Hash + 'static,
|
|
||||||
Lens: Readable<Target = T> + 'static,
|
Lens: Readable<Target = T> + 'static,
|
||||||
{
|
{
|
||||||
self.into_selector()
|
T::scope_selector(self.into_selector(), &index)
|
||||||
.hash_child_unmapped(&index)
|
|
||||||
.map_writer(move |write| IndexWrite { index, write })
|
.map_writer(move |write| IndexWrite { index, write })
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
mod btreemap;
|
pub mod btreemap;
|
||||||
mod deref;
|
mod deref;
|
||||||
mod hashmap;
|
pub mod hashmap;
|
||||||
mod index;
|
pub mod index;
|
||||||
mod option;
|
mod option;
|
||||||
mod result;
|
mod result;
|
||||||
mod slice;
|
mod slice;
|
||||||
|
|||||||
@@ -57,4 +57,27 @@ where
|
|||||||
{
|
{
|
||||||
(0..self.len()).map(move |i| self.clone().index(i))
|
(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 impls;
|
||||||
mod store;
|
mod store;
|
||||||
mod subscriptions;
|
mod subscriptions;
|
||||||
|
pub use impls::*;
|
||||||
pub use store::*;
|
pub use store::*;
|
||||||
pub mod scope;
|
pub mod scope;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user