1use std::{
4 collections::{BTreeMap, HashMap},
5 hash::Hash,
6 ops::{self, Index, IndexMut},
7};
8
9use crate::{scope::SelectorScope, store::Store, ReadStore};
10use dioxus_signals::{
11 AnyStorage, BorrowError, BorrowMutError, ReadSignal, Readable, UnsyncStorage, Writable,
12 WriteLock, WriteSignal,
13};
14
15pub trait IndexSelector<Idx> {
18 fn scope_selector<Lens>(selector: SelectorScope<Lens>, index: &Idx) -> SelectorScope<Lens>;
20}
21
22impl<T> IndexSelector<usize> for Vec<T> {
23 fn scope_selector<Lens>(selector: SelectorScope<Lens>, index: &usize) -> SelectorScope<Lens> {
24 selector.child_unmapped(*index as _)
25 }
26}
27
28impl<T> IndexSelector<usize> for [T] {
29 fn scope_selector<Lens>(selector: SelectorScope<Lens>, index: &usize) -> SelectorScope<Lens> {
30 selector.child_unmapped(*index as _)
31 }
32}
33
34impl<K, V, I> IndexSelector<I> for HashMap<K, V>
35where
36 I: Hash,
37{
38 fn scope_selector<Lens>(selector: SelectorScope<Lens>, index: &I) -> SelectorScope<Lens> {
39 selector.hash_child_unmapped(&index)
40 }
41}
42
43impl<K, V, I> IndexSelector<I> for BTreeMap<K, V>
44where
45 I: Hash,
46{
47 fn scope_selector<Lens>(selector: SelectorScope<Lens>, index: &I) -> SelectorScope<Lens> {
48 selector.hash_child_unmapped(&index)
49 }
50}
51
52impl<Lens, T> Store<T, Lens> {
53 pub fn index<Idx>(self, index: Idx) -> Store<T::Output, IndexWrite<Idx, Lens>>
65 where
66 T: IndexMut<Idx> + 'static + IndexSelector<Idx>,
67 Lens: Readable<Target = T> + 'static,
68 {
69 T::scope_selector(self.into_selector(), &index)
70 .map_writer(move |write| IndexWrite { index, write })
71 .into()
72 }
73}
74
75#[derive(Clone, Copy)]
77pub struct IndexWrite<Index, Write> {
78 index: Index,
79 write: Write,
80}
81
82impl<Index, Write> Readable for IndexWrite<Index, Write>
83where
84 Write: Readable,
85 Write::Target: ops::Index<Index> + 'static,
86 Index: Clone,
87{
88 type Target = <Write::Target as ops::Index<Index>>::Output;
89
90 type Storage = Write::Storage;
91
92 fn try_read_unchecked(&self) -> Result<dioxus_signals::ReadableRef<'static, Self>, BorrowError>
93 where
94 Self::Target: 'static,
95 {
96 self.write.try_read_unchecked().map(|value| {
97 Self::Storage::map(value, |value: &Write::Target| {
98 value.index(self.index.clone())
99 })
100 })
101 }
102
103 fn try_peek_unchecked(&self) -> Result<dioxus_signals::ReadableRef<'static, Self>, BorrowError>
104 where
105 Self::Target: 'static,
106 {
107 self.write.try_peek_unchecked().map(|value| {
108 Self::Storage::map(value, |value: &Write::Target| {
109 value.index(self.index.clone())
110 })
111 })
112 }
113
114 fn subscribers(&self) -> dioxus_core::Subscribers
115 where
116 Self::Target: 'static,
117 {
118 self.write.subscribers()
119 }
120}
121
122impl<Index, Write> Writable for IndexWrite<Index, Write>
123where
124 Write: Writable,
125 Write::Target: ops::IndexMut<Index> + 'static,
126 Index: Clone,
127{
128 type WriteMetadata = Write::WriteMetadata;
129
130 fn try_write_unchecked(
131 &self,
132 ) -> Result<dioxus_signals::WritableRef<'static, Self>, BorrowMutError>
133 where
134 Self::Target: 'static,
135 {
136 self.write.try_write_unchecked().map(|value| {
137 WriteLock::map(value, |value: &mut Write::Target| {
138 value.index_mut(self.index.clone())
139 })
140 })
141 }
142}
143
144impl<Idx, T, Write> ::std::convert::From<Store<T, IndexWrite<Idx, Write>>>
145 for Store<T, WriteSignal<T>>
146where
147 Write: Writable<Storage = UnsyncStorage> + 'static,
148 Write::WriteMetadata: 'static,
149 Write::Target: ops::IndexMut<Idx, Output = T> + 'static,
150 Idx: Clone + 'static,
151 T: 'static,
152{
153 fn from(value: Store<T, IndexWrite<Idx, Write>>) -> Self {
154 value
155 .into_selector()
156 .map_writer(|writer| WriteSignal::new(writer))
157 .into()
158 }
159}
160
161impl<Idx, T, Write> ::std::convert::From<Store<T, IndexWrite<Idx, Write>>> for ReadStore<T>
162where
163 Write: Readable<Storage = UnsyncStorage> + 'static,
164 Write::Target: ops::Index<Idx, Output = T> + 'static,
165 Idx: Clone + 'static,
166 T: 'static,
167{
168 fn from(value: Store<T, IndexWrite<Idx, Write>>) -> Self {
169 value
170 .into_selector()
171 .map_writer(|writer| ReadSignal::new(writer))
172 .into()
173 }
174}