1use crate::{
2 path::{StorePath, StorePathSegment},
3 store_field::StoreField,
4 KeyMap, StoreFieldTrigger,
5};
6use reactive_graph::{
7 signal::{
8 guards::{Mapped, MappedMut, MappedMutArc, WriteGuard},
9 ArcTrigger,
10 },
11 traits::{
12 DefinedAt, IsDisposed, Notify, ReadUntracked, Track, UntrackableGuard,
13 Write,
14 },
15};
16use std::{
17 collections::VecDeque,
18 fmt::Debug,
19 hash::Hash,
20 iter,
21 ops::{Deref, DerefMut, IndexMut},
22 panic::Location,
23};
24
25#[derive(Debug)]
27pub struct KeyedSubfield<Inner, Prev, K, T>
28where
29 for<'a> &'a T: IntoIterator,
30{
31 #[cfg(any(debug_assertions, leptos_debuginfo))]
32 defined_at: &'static Location<'static>,
33 path_segment: StorePathSegment,
34 inner: Inner,
35 read: fn(&Prev) -> &T,
36 write: fn(&mut Prev) -> &mut T,
37 key_fn: fn(<&T as IntoIterator>::Item) -> K,
38}
39
40impl<Inner, Prev, K, T> Clone for KeyedSubfield<Inner, Prev, K, T>
41where
42 for<'a> &'a T: IntoIterator,
43 Inner: Clone,
44{
45 fn clone(&self) -> Self {
46 Self {
47 #[cfg(any(debug_assertions, leptos_debuginfo))]
48 defined_at: self.defined_at,
49 path_segment: self.path_segment,
50 inner: self.inner.clone(),
51 read: self.read,
52 write: self.write,
53 key_fn: self.key_fn,
54 }
55 }
56}
57
58impl<Inner, Prev, K, T> Copy for KeyedSubfield<Inner, Prev, K, T>
59where
60 for<'a> &'a T: IntoIterator,
61 Inner: Copy,
62{
63}
64
65impl<Inner, Prev, K, T> KeyedSubfield<Inner, Prev, K, T>
66where
67 for<'a> &'a T: IntoIterator,
68{
69 #[track_caller]
71 pub fn new(
72 inner: Inner,
73 path_segment: StorePathSegment,
74 key_fn: fn(<&T as IntoIterator>::Item) -> K,
75 read: fn(&Prev) -> &T,
76 write: fn(&mut Prev) -> &mut T,
77 ) -> Self {
78 Self {
79 #[cfg(any(debug_assertions, leptos_debuginfo))]
80 defined_at: Location::caller(),
81 inner,
82 path_segment,
83 read,
84 write,
85 key_fn,
86 }
87 }
88}
89
90impl<Inner, Prev, K, T> StoreField for KeyedSubfield<Inner, Prev, K, T>
91where
92 Self: Clone,
93 for<'a> &'a T: IntoIterator,
94 Inner: StoreField<Value = Prev>,
95 Prev: 'static,
96 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
97{
98 type Value = T;
99 type Reader = Mapped<Inner::Reader, T>;
100 type Writer = MappedMut<WriteGuard<Vec<ArcTrigger>, Inner::Writer>, T>;
101
102 fn path(&self) -> impl IntoIterator<Item = StorePathSegment> {
103 self.inner
104 .path()
105 .into_iter()
106 .chain(iter::once(self.path_segment))
107 }
108
109 fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
110 self.inner.get_trigger(path)
111 }
112
113 fn reader(&self) -> Option<Self::Reader> {
114 let inner = self.inner.reader()?;
115 Some(Mapped::new_with_guard(inner, self.read))
116 }
117
118 fn writer(&self) -> Option<Self::Writer> {
119 let mut parent = self.inner.writer()?;
120 parent.untrack();
121 let triggers = self.triggers_for_current_path();
122 let guard = WriteGuard::new(triggers, parent);
123 Some(MappedMut::new(guard, self.read, self.write))
124 }
125
126 #[inline(always)]
127 fn keys(&self) -> Option<KeyMap> {
128 self.inner.keys()
129 }
130
131 fn track_field(&self) {
132 let inner = self
133 .inner
134 .get_trigger(self.inner.path().into_iter().collect());
135 inner.this.track();
136 let trigger = self.get_trigger(self.path().into_iter().collect());
137 trigger.this.track();
138 trigger.children.track();
139 }
140}
141
142impl<Inner, Prev, K, T> KeyedSubfield<Inner, Prev, K, T>
143where
144 Self: Clone,
145 for<'a> &'a T: IntoIterator,
146 Inner: StoreField<Value = Prev>,
147 Prev: 'static,
148 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
149{
150 fn latest_keys(&self) -> Vec<K> {
151 self.reader()
152 .map(|r| r.deref().into_iter().map(|n| (self.key_fn)(n)).collect())
153 .unwrap_or_default()
154 }
155}
156
157pub struct KeyedSubfieldWriteGuard<Inner, Prev, K, T, Guard>
159where
160 KeyedSubfield<Inner, Prev, K, T>: Clone,
161 for<'a> &'a T: IntoIterator,
162 Inner: StoreField<Value = Prev>,
163 Prev: 'static,
164 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
165{
166 inner: KeyedSubfield<Inner, Prev, K, T>,
167 guard: Option<Guard>,
168}
169
170impl<Inner, Prev, K, T, Guard> Deref
171 for KeyedSubfieldWriteGuard<Inner, Prev, K, T, Guard>
172where
173 Guard: Deref,
174 KeyedSubfield<Inner, Prev, K, T>: Clone,
175 for<'a> &'a T: IntoIterator,
176 Inner: StoreField<Value = Prev>,
177 Prev: 'static,
178 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
179{
180 type Target = Guard::Target;
181
182 fn deref(&self) -> &Self::Target {
183 self.guard
184 .as_ref()
185 .expect("should be Some(_) until dropped")
186 .deref()
187 }
188}
189
190impl<Inner, Prev, K, T, Guard> DerefMut
191 for KeyedSubfieldWriteGuard<Inner, Prev, K, T, Guard>
192where
193 Guard: DerefMut,
194 KeyedSubfield<Inner, Prev, K, T>: Clone,
195 for<'a> &'a T: IntoIterator,
196 Inner: StoreField<Value = Prev>,
197 Prev: 'static,
198 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
199{
200 fn deref_mut(&mut self) -> &mut Self::Target {
201 self.guard
202 .as_mut()
203 .expect("should be Some(_) until dropped")
204 .deref_mut()
205 }
206}
207
208impl<Inner, Prev, K, T, Guard> UntrackableGuard
209 for KeyedSubfieldWriteGuard<Inner, Prev, K, T, Guard>
210where
211 Guard: UntrackableGuard,
212 KeyedSubfield<Inner, Prev, K, T>: Clone,
213 for<'a> &'a T: IntoIterator,
214 Inner: StoreField<Value = Prev>,
215 Prev: 'static,
216 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
217{
218 fn untrack(&mut self) {
219 if let Some(inner) = self.guard.as_mut() {
220 inner.untrack();
221 }
222 }
223}
224
225impl<Inner, Prev, K, T, Guard> Drop
226 for KeyedSubfieldWriteGuard<Inner, Prev, K, T, Guard>
227where
228 KeyedSubfield<Inner, Prev, K, T>: Clone,
229 for<'a> &'a T: IntoIterator,
230 Inner: StoreField<Value = Prev>,
231 Prev: 'static,
232 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
233{
234 fn drop(&mut self) {
235 drop(self.guard.take());
239
240 self.inner.update_keys();
243 self.inner.notify();
244
245 }
247}
248
249impl<Inner, Prev, K, T> DefinedAt for KeyedSubfield<Inner, Prev, K, T>
250where
251 for<'a> &'a T: IntoIterator,
252 Inner: StoreField<Value = Prev>,
253{
254 fn defined_at(&self) -> Option<&'static Location<'static>> {
255 #[cfg(any(debug_assertions, leptos_debuginfo))]
256 {
257 Some(self.defined_at)
258 }
259 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
260 {
261 None
262 }
263 }
264}
265
266impl<Inner, Prev, K, T> IsDisposed for KeyedSubfield<Inner, Prev, K, T>
267where
268 for<'a> &'a T: IntoIterator,
269 Inner: IsDisposed,
270{
271 fn is_disposed(&self) -> bool {
272 self.inner.is_disposed()
273 }
274}
275
276impl<Inner, Prev, K, T> Notify for KeyedSubfield<Inner, Prev, K, T>
277where
278 Self: Clone,
279 for<'a> &'a T: IntoIterator,
280 Inner: StoreField<Value = Prev>,
281 Prev: 'static,
282 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
283{
284 fn notify(&self) {
285 let trigger = self.get_trigger(self.path().into_iter().collect());
286 trigger.this.notify();
287 trigger.children.notify();
288 }
289}
290
291impl<Inner, Prev, K, T> Track for KeyedSubfield<Inner, Prev, K, T>
292where
293 Self: Clone,
294 for<'a> &'a T: IntoIterator,
295 Inner: StoreField<Value = Prev> + Track + 'static,
296 Prev: 'static,
297 T: 'static,
298 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
299{
300 fn track(&self) {
301 self.track_field();
302 }
303}
304
305impl<Inner, Prev, K, T> ReadUntracked for KeyedSubfield<Inner, Prev, K, T>
306where
307 Self: Clone,
308 for<'a> &'a T: IntoIterator,
309 Inner: StoreField<Value = Prev>,
310 Prev: 'static,
311 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
312{
313 type Value = <Self as StoreField>::Reader;
314
315 fn try_read_untracked(&self) -> Option<Self::Value> {
316 self.reader()
317 }
318}
319
320impl<Inner, Prev, K, T> Write for KeyedSubfield<Inner, Prev, K, T>
321where
322 Self: Clone,
323 for<'a> &'a T: IntoIterator,
324 T: 'static,
325 Inner: StoreField<Value = Prev>,
326 Prev: 'static,
327 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
328{
329 type Value = T;
330
331 fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
332 let guard = self.writer()?;
333 Some(KeyedSubfieldWriteGuard {
334 inner: self.clone(),
335 guard: Some(guard),
336 })
337 }
338
339 fn try_write_untracked(
340 &self,
341 ) -> Option<impl DerefMut<Target = Self::Value>> {
342 let mut guard = self.writer()?;
343 guard.untrack();
344 Some(KeyedSubfieldWriteGuard {
345 inner: self.clone(),
346 guard: Some(guard),
347 })
348 }
349}
350
351#[derive(Debug)]
353pub struct AtKeyed<Inner, Prev, K, T>
354where
355 for<'a> &'a T: IntoIterator,
356{
357 #[cfg(any(debug_assertions, leptos_debuginfo))]
358 defined_at: &'static Location<'static>,
359 inner: KeyedSubfield<Inner, Prev, K, T>,
360 key: K,
361}
362
363impl<Inner, Prev, K, T> Clone for AtKeyed<Inner, Prev, K, T>
364where
365 for<'a> &'a T: IntoIterator,
366 KeyedSubfield<Inner, Prev, K, T>: Clone,
367 K: Debug + Clone,
368{
369 fn clone(&self) -> Self {
370 Self {
371 #[cfg(any(debug_assertions, leptos_debuginfo))]
372 defined_at: self.defined_at,
373 inner: self.inner.clone(),
374 key: self.key.clone(),
375 }
376 }
377}
378
379impl<Inner, Prev, K, T> Copy for AtKeyed<Inner, Prev, K, T>
380where
381 for<'a> &'a T: IntoIterator,
382 KeyedSubfield<Inner, Prev, K, T>: Copy,
383 K: Debug + Copy,
384{
385}
386
387impl<Inner, Prev, K, T> AtKeyed<Inner, Prev, K, T>
388where
389 for<'a> &'a T: IntoIterator,
390{
391 #[track_caller]
393 pub fn new(inner: KeyedSubfield<Inner, Prev, K, T>, key: K) -> Self {
394 Self {
395 #[cfg(any(debug_assertions, leptos_debuginfo))]
396 defined_at: Location::caller(),
397 inner,
398 key,
399 }
400 }
401}
402
403impl<Inner, Prev, K, T> StoreField for AtKeyed<Inner, Prev, K, T>
404where
405 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
406 KeyedSubfield<Inner, Prev, K, T>: Clone,
407 for<'a> &'a T: IntoIterator,
408 Inner: StoreField<Value = Prev>,
409 Prev: 'static,
410 T: IndexMut<usize>,
411 T::Output: Sized,
412{
413 type Value = T::Output;
414 type Reader = MappedMutArc<
415 <KeyedSubfield<Inner, Prev, K, T> as StoreField>::Reader,
416 T::Output,
417 >;
418 type Writer = WriteGuard<
419 Vec<ArcTrigger>,
420 MappedMutArc<
421 <KeyedSubfield<Inner, Prev, K, T> as StoreField>::Writer,
422 T::Output,
423 >,
424 >;
425
426 fn path(&self) -> impl IntoIterator<Item = StorePathSegment> {
427 let inner = self.inner.path().into_iter().collect::<StorePath>();
428 let keys = self
429 .inner
430 .keys()
431 .expect("using keys on a store with no keys");
432 let this = keys
433 .with_field_keys(
434 inner.clone(),
435 |keys| keys.get(&self.key),
436 || self.inner.latest_keys(),
437 )
438 .flatten()
439 .map(|(path, _)| path);
440 inner.into_iter().chain(this)
441 }
442
443 fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
444 self.inner.get_trigger(path)
445 }
446
447 fn reader(&self) -> Option<Self::Reader> {
448 let inner = self.inner.reader()?;
449
450 let inner_path = self.inner.path().into_iter().collect();
451 let keys = self.inner.keys()?;
452 let index = keys
453 .with_field_keys(
454 inner_path,
455 |keys| keys.get(&self.key),
456 || self.inner.latest_keys(),
457 )
458 .flatten()
459 .map(|(_, idx)| idx)?;
460
461 Some(MappedMutArc::new(
462 inner,
463 move |n| &n[index],
464 move |n| &mut n[index],
465 ))
466 }
467
468 fn writer(&self) -> Option<Self::Writer> {
469 let mut inner = self.inner.writer()?;
470 inner.untrack();
471 let inner_path = self.inner.path().into_iter().collect::<StorePath>();
472 let keys = self
473 .inner
474 .keys()
475 .expect("using keys on a store with no keys");
476 let index = keys
477 .with_field_keys(
478 inner_path.clone(),
479 |keys| keys.get(&self.key),
480 || self.inner.latest_keys(),
481 )
482 .flatten()
483 .map(|(_, idx)| idx)?;
484
485 let triggers = self.triggers_for_current_path();
486
487 Some(WriteGuard::new(
488 triggers,
489 MappedMutArc::new(
490 inner,
491 move |n| &n[index],
492 move |n| &mut n[index],
493 ),
494 ))
495 }
496
497 #[inline(always)]
498 fn keys(&self) -> Option<KeyMap> {
499 self.inner.keys()
500 }
501}
502
503impl<Inner, Prev, K, T> DefinedAt for AtKeyed<Inner, Prev, K, T>
504where
505 for<'a> &'a T: IntoIterator,
506{
507 fn defined_at(&self) -> Option<&'static Location<'static>> {
508 #[cfg(any(debug_assertions, leptos_debuginfo))]
509 {
510 Some(self.defined_at)
511 }
512 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
513 {
514 None
515 }
516 }
517}
518
519impl<Inner, Prev, K, T> IsDisposed for AtKeyed<Inner, Prev, K, T>
520where
521 for<'a> &'a T: IntoIterator,
522 Inner: IsDisposed,
523{
524 fn is_disposed(&self) -> bool {
525 self.inner.is_disposed()
526 }
527}
528
529impl<Inner, Prev, K, T> Notify for AtKeyed<Inner, Prev, K, T>
530where
531 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
532 KeyedSubfield<Inner, Prev, K, T>: Clone,
533 for<'a> &'a T: IntoIterator,
534 Inner: StoreField<Value = Prev>,
535 Prev: 'static,
536 T: IndexMut<usize>,
537 T::Output: Sized,
538{
539 fn notify(&self) {
540 let trigger = self.get_trigger(self.path().into_iter().collect());
541 trigger.this.notify();
542 trigger.children.notify();
543 }
544}
545
546impl<Inner, Prev, K, T> Track for AtKeyed<Inner, Prev, K, T>
547where
548 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
549 KeyedSubfield<Inner, Prev, K, T>: Clone,
550 for<'a> &'a T: IntoIterator,
551 Inner: StoreField<Value = Prev>,
552 Prev: 'static,
553 T: IndexMut<usize>,
554 T::Output: Sized,
555{
556 fn track(&self) {
557 self.track_field();
558 }
559}
560
561impl<Inner, Prev, K, T> ReadUntracked for AtKeyed<Inner, Prev, K, T>
562where
563 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
564 KeyedSubfield<Inner, Prev, K, T>: Clone,
565 for<'a> &'a T: IntoIterator,
566 Inner: StoreField<Value = Prev>,
567 Prev: 'static,
568 T: IndexMut<usize>,
569 T::Output: Sized,
570{
571 type Value = <Self as StoreField>::Reader;
572
573 fn try_read_untracked(&self) -> Option<Self::Value> {
574 self.reader()
575 }
576}
577
578impl<Inner, Prev, K, T> Write for AtKeyed<Inner, Prev, K, T>
579where
580 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
581 KeyedSubfield<Inner, Prev, K, T>: Clone,
582 for<'a> &'a T: IntoIterator,
583 Inner: StoreField<Value = Prev>,
584 Prev: 'static,
585 T: IndexMut<usize>,
586 T::Output: Sized + 'static,
587{
588 type Value = T::Output;
589
590 fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
591 self.writer()
592 }
593
594 fn try_write_untracked(
595 &self,
596 ) -> Option<impl DerefMut<Target = Self::Value>> {
597 self.writer().map(|mut writer| {
598 writer.untrack();
599 writer
600 })
601 }
602}
603
604impl<Inner, Prev, K, T> KeyedSubfield<Inner, Prev, K, T>
605where
606 Self: Clone,
607 for<'a> &'a T: IntoIterator,
608 Inner: StoreField<Value = Prev>,
609 Prev: 'static,
610 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
611{
612 pub fn update_keys(&self) {
614 let inner_path = self.path().into_iter().collect();
615 let keys = self
616 .inner
617 .keys()
618 .expect("updating keys on a store with no keys");
619
620 let latest = self.latest_keys();
625 keys.with_field_keys(
626 inner_path,
627 |keys| {
628 keys.update(latest);
629 },
630 || self.latest_keys(),
631 );
632 }
633}
634
635impl<Inner, Prev, K, T> IntoIterator for KeyedSubfield<Inner, Prev, K, T>
636where
637 Self: Clone,
638 for<'a> &'a T: IntoIterator,
639 Inner: Clone + StoreField<Value = Prev> + 'static,
640 Prev: 'static,
641 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
642 T: IndexMut<usize> + 'static,
643 T::Output: Sized,
644{
645 type Item = AtKeyed<Inner, Prev, K, T>;
646 type IntoIter = StoreFieldKeyedIter<Inner, Prev, K, T>;
647
648 #[track_caller]
649 fn into_iter(self) -> StoreFieldKeyedIter<Inner, Prev, K, T> {
650 self.update_keys();
652 self.track_field();
653
654 let reader = self.reader();
656
657 let keys = reader
658 .map(|r| {
659 r.into_iter()
660 .map(|item| (self.key_fn)(item))
661 .collect::<VecDeque<_>>()
662 })
663 .unwrap_or_default();
664
665 StoreFieldKeyedIter { inner: self, keys }
667 }
668}
669
670pub struct StoreFieldKeyedIter<Inner, Prev, K, T>
672where
673 for<'a> &'a T: IntoIterator,
674 T: IndexMut<usize>,
675{
676 inner: KeyedSubfield<Inner, Prev, K, T>,
677 keys: VecDeque<K>,
678}
679
680impl<Inner, Prev, K, T> Iterator for StoreFieldKeyedIter<Inner, Prev, K, T>
681where
682 Inner: StoreField<Value = Prev> + Clone + 'static,
683 T: IndexMut<usize> + 'static,
684 T::Output: Sized + 'static,
685 for<'a> &'a T: IntoIterator,
686{
687 type Item = AtKeyed<Inner, Prev, K, T>;
688
689 fn next(&mut self) -> Option<Self::Item> {
690 self.keys
691 .pop_front()
692 .map(|key| AtKeyed::new(self.inner.clone(), key))
693 }
694}
695
696impl<Inner, Prev, K, T> DoubleEndedIterator
697 for StoreFieldKeyedIter<Inner, Prev, K, T>
698where
699 Inner: StoreField<Value = Prev> + Clone + 'static,
700 T: IndexMut<usize> + 'static,
701 T::Output: Sized + 'static,
702 for<'a> &'a T: IntoIterator,
703{
704 fn next_back(&mut self) -> Option<Self::Item> {
705 self.keys
706 .pop_back()
707 .map(|key| AtKeyed::new(self.inner.clone(), key))
708 }
709}