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<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 path = self.path().into_iter().collect::<StorePath>();
120 let trigger = self.get_trigger(path.clone());
121 let guard = WriteGuard::new(trigger.children, self.inner.writer()?);
122 Some(MappedMut::new(guard, self.read, self.write))
123 }
124
125 #[inline(always)]
126 fn keys(&self) -> Option<KeyMap> {
127 self.inner.keys()
128 }
129
130 fn track_field(&self) {
131 let inner = self
132 .inner
133 .get_trigger(self.inner.path().into_iter().collect());
134 inner.this.track();
135 let trigger = self.get_trigger(self.path().into_iter().collect());
136 trigger.this.track();
137 trigger.children.track();
138 }
139}
140
141impl<Inner, Prev, K, T> KeyedSubfield<Inner, Prev, K, T>
142where
143 Self: Clone,
144 for<'a> &'a T: IntoIterator,
145 Inner: StoreField<Value = Prev>,
146 Prev: 'static,
147 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
148{
149 fn latest_keys(&self) -> Vec<K> {
150 self.reader()
151 .map(|r| r.deref().into_iter().map(|n| (self.key_fn)(n)).collect())
152 .unwrap_or_default()
153 }
154}
155
156pub struct KeyedSubfieldWriteGuard<Inner, Prev, K, T, Guard>
158where
159 KeyedSubfield<Inner, Prev, K, T>: Clone,
160 for<'a> &'a T: IntoIterator,
161 Inner: StoreField<Value = Prev>,
162 Prev: 'static,
163 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
164{
165 inner: KeyedSubfield<Inner, Prev, K, T>,
166 guard: Option<Guard>,
167}
168
169impl<Inner, Prev, K, T, Guard> Deref
170 for KeyedSubfieldWriteGuard<Inner, Prev, K, T, Guard>
171where
172 Guard: Deref,
173 KeyedSubfield<Inner, Prev, K, T>: Clone,
174 for<'a> &'a T: IntoIterator,
175 Inner: StoreField<Value = Prev>,
176 Prev: 'static,
177 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
178{
179 type Target = Guard::Target;
180
181 fn deref(&self) -> &Self::Target {
182 self.guard
183 .as_ref()
184 .expect("should be Some(_) until dropped")
185 .deref()
186 }
187}
188
189impl<Inner, Prev, K, T, Guard> DerefMut
190 for KeyedSubfieldWriteGuard<Inner, Prev, K, T, Guard>
191where
192 Guard: DerefMut,
193 KeyedSubfield<Inner, Prev, K, T>: Clone,
194 for<'a> &'a T: IntoIterator,
195 Inner: StoreField<Value = Prev>,
196 Prev: 'static,
197 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
198{
199 fn deref_mut(&mut self) -> &mut Self::Target {
200 self.guard
201 .as_mut()
202 .expect("should be Some(_) until dropped")
203 .deref_mut()
204 }
205}
206
207impl<Inner, Prev, K, T, Guard> UntrackableGuard
208 for KeyedSubfieldWriteGuard<Inner, Prev, K, T, Guard>
209where
210 Guard: UntrackableGuard,
211 KeyedSubfield<Inner, Prev, K, T>: Clone,
212 for<'a> &'a T: IntoIterator,
213 Inner: StoreField<Value = Prev>,
214 Prev: 'static,
215 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
216{
217 fn untrack(&mut self) {
218 if let Some(inner) = self.guard.as_mut() {
219 inner.untrack();
220 }
221 }
222}
223
224impl<Inner, Prev, K, T, Guard> Drop
225 for KeyedSubfieldWriteGuard<Inner, Prev, K, T, Guard>
226where
227 KeyedSubfield<Inner, Prev, K, T>: Clone,
228 for<'a> &'a T: IntoIterator,
229 Inner: StoreField<Value = Prev>,
230 Prev: 'static,
231 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
232{
233 fn drop(&mut self) {
234 drop(self.guard.take());
238
239 self.inner.update_keys();
242 self.inner.notify();
243
244 }
246}
247
248impl<Inner, Prev, K, T> DefinedAt for KeyedSubfield<Inner, Prev, K, T>
249where
250 for<'a> &'a T: IntoIterator,
251 Inner: StoreField<Value = Prev>,
252{
253 fn defined_at(&self) -> Option<&'static Location<'static>> {
254 #[cfg(any(debug_assertions, leptos_debuginfo))]
255 {
256 Some(self.defined_at)
257 }
258 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
259 {
260 None
261 }
262 }
263}
264
265impl<Inner, Prev, K, T> IsDisposed for KeyedSubfield<Inner, Prev, K, T>
266where
267 for<'a> &'a T: IntoIterator,
268 Inner: IsDisposed,
269{
270 fn is_disposed(&self) -> bool {
271 self.inner.is_disposed()
272 }
273}
274
275impl<Inner, Prev, K, T> Notify for KeyedSubfield<Inner, Prev, K, T>
276where
277 Self: Clone,
278 for<'a> &'a T: IntoIterator,
279 Inner: StoreField<Value = Prev>,
280 Prev: 'static,
281 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
282{
283 fn notify(&self) {
284 let trigger = self.get_trigger(self.path().into_iter().collect());
285 trigger.this.notify();
286 trigger.children.notify();
287 }
288}
289
290impl<Inner, Prev, K, T> Track for KeyedSubfield<Inner, Prev, K, T>
291where
292 Self: Clone,
293 for<'a> &'a T: IntoIterator,
294 Inner: StoreField<Value = Prev> + Track + 'static,
295 Prev: 'static,
296 T: 'static,
297 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
298{
299 fn track(&self) {
300 self.track_field();
301 }
302}
303
304impl<Inner, Prev, K, T> ReadUntracked for KeyedSubfield<Inner, Prev, K, T>
305where
306 Self: Clone,
307 for<'a> &'a T: IntoIterator,
308 Inner: StoreField<Value = Prev>,
309 Prev: 'static,
310 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
311{
312 type Value = <Self as StoreField>::Reader;
313
314 fn try_read_untracked(&self) -> Option<Self::Value> {
315 self.reader()
316 }
317}
318
319impl<Inner, Prev, K, T> Write for KeyedSubfield<Inner, Prev, K, T>
320where
321 Self: Clone,
322 for<'a> &'a T: IntoIterator,
323 T: 'static,
324 Inner: StoreField<Value = Prev>,
325 Prev: 'static,
326 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
327{
328 type Value = T;
329
330 fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
331 let guard = self.writer()?;
332 Some(KeyedSubfieldWriteGuard {
333 inner: self.clone(),
334 guard: Some(guard),
335 })
336 }
337
338 fn try_write_untracked(
339 &self,
340 ) -> Option<impl DerefMut<Target = Self::Value>> {
341 let mut guard = self.writer()?;
342 guard.untrack();
343 Some(KeyedSubfieldWriteGuard {
344 inner: self.clone(),
345 guard: Some(guard),
346 })
347 }
348}
349
350#[derive(Debug)]
352pub struct AtKeyed<Inner, Prev, K, T>
353where
354 for<'a> &'a T: IntoIterator,
355{
356 #[cfg(any(debug_assertions, leptos_debuginfo))]
357 defined_at: &'static Location<'static>,
358 inner: KeyedSubfield<Inner, Prev, K, T>,
359 key: K,
360}
361
362impl<Inner, Prev, K, T> Clone for AtKeyed<Inner, Prev, K, T>
363where
364 for<'a> &'a T: IntoIterator,
365 KeyedSubfield<Inner, Prev, K, T>: Clone,
366 K: Debug + Clone,
367{
368 fn clone(&self) -> Self {
369 Self {
370 #[cfg(any(debug_assertions, leptos_debuginfo))]
371 defined_at: self.defined_at,
372 inner: self.inner.clone(),
373 key: self.key.clone(),
374 }
375 }
376}
377
378impl<Inner, Prev, K, T> Copy for AtKeyed<Inner, Prev, K, T>
379where
380 for<'a> &'a T: IntoIterator,
381 KeyedSubfield<Inner, Prev, K, T>: Copy,
382 K: Debug + Copy,
383{
384}
385
386impl<Inner, Prev, K, T> AtKeyed<Inner, Prev, K, T>
387where
388 for<'a> &'a T: IntoIterator,
389{
390 #[track_caller]
392 pub fn new(inner: KeyedSubfield<Inner, Prev, K, T>, key: K) -> Self {
393 Self {
394 #[cfg(any(debug_assertions, leptos_debuginfo))]
395 defined_at: Location::caller(),
396 inner,
397 key,
398 }
399 }
400}
401
402impl<Inner, Prev, K, T> StoreField for AtKeyed<Inner, Prev, K, T>
403where
404 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
405 KeyedSubfield<Inner, Prev, K, T>: Clone,
406 for<'a> &'a T: IntoIterator,
407 Inner: StoreField<Value = Prev>,
408 Prev: 'static,
409 T: IndexMut<usize>,
410 T::Output: Sized,
411{
412 type Value = T::Output;
413 type Reader = MappedMutArc<
414 <KeyedSubfield<Inner, Prev, K, T> as StoreField>::Reader,
415 T::Output,
416 >;
417 type Writer = WriteGuard<
418 ArcTrigger,
419 MappedMutArc<
420 <KeyedSubfield<Inner, Prev, K, T> as StoreField>::Writer,
421 T::Output,
422 >,
423 >;
424
425 fn path(&self) -> impl IntoIterator<Item = StorePathSegment> {
426 let inner = self.inner.path().into_iter().collect::<StorePath>();
427 let keys = self
428 .inner
429 .keys()
430 .expect("using keys on a store with no keys");
431 let this = keys
432 .with_field_keys(
433 inner.clone(),
434 |keys| keys.get(&self.key),
435 || self.inner.latest_keys(),
436 )
437 .flatten()
438 .map(|(path, _)| path);
439 inner.into_iter().chain(this)
440 }
441
442 fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
443 self.inner.get_trigger(path)
444 }
445
446 fn reader(&self) -> Option<Self::Reader> {
447 let inner = self.inner.reader()?;
448
449 let inner_path = self.inner.path().into_iter().collect();
450 let keys = self.inner.keys()?;
451 let index = keys
452 .with_field_keys(
453 inner_path,
454 |keys| keys.get(&self.key),
455 || self.inner.latest_keys(),
456 )
457 .flatten()
458 .map(|(_, idx)| idx)?;
459
460 Some(MappedMutArc::new(
461 inner,
462 move |n| &n[index],
463 move |n| &mut n[index],
464 ))
465 }
466
467 fn writer(&self) -> Option<Self::Writer> {
468 let inner = self.inner.writer()?;
469 let trigger = self.get_trigger(self.path().into_iter().collect());
470
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 Some(WriteGuard::new(
486 trigger.children,
487 MappedMutArc::new(
488 inner,
489 move |n| &n[index],
490 move |n| &mut n[index],
491 ),
492 ))
493 }
494
495 #[inline(always)]
496 fn keys(&self) -> Option<KeyMap> {
497 self.inner.keys()
498 }
499}
500
501impl<Inner, Prev, K, T> DefinedAt for AtKeyed<Inner, Prev, K, T>
502where
503 for<'a> &'a T: IntoIterator,
504{
505 fn defined_at(&self) -> Option<&'static Location<'static>> {
506 #[cfg(any(debug_assertions, leptos_debuginfo))]
507 {
508 Some(self.defined_at)
509 }
510 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
511 {
512 None
513 }
514 }
515}
516
517impl<Inner, Prev, K, T> IsDisposed for AtKeyed<Inner, Prev, K, T>
518where
519 for<'a> &'a T: IntoIterator,
520 Inner: IsDisposed,
521{
522 fn is_disposed(&self) -> bool {
523 self.inner.is_disposed()
524 }
525}
526
527impl<Inner, Prev, K, T> Notify for AtKeyed<Inner, Prev, K, T>
528where
529 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
530 KeyedSubfield<Inner, Prev, K, T>: Clone,
531 for<'a> &'a T: IntoIterator,
532 Inner: StoreField<Value = Prev>,
533 Prev: 'static,
534 T: IndexMut<usize>,
535 T::Output: Sized,
536{
537 fn notify(&self) {
538 let trigger = self.get_trigger(self.path().into_iter().collect());
539 trigger.this.notify();
540 trigger.children.notify();
541 }
542}
543
544impl<Inner, Prev, K, T> Track for AtKeyed<Inner, Prev, K, T>
545where
546 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
547 KeyedSubfield<Inner, Prev, K, T>: Clone,
548 for<'a> &'a T: IntoIterator,
549 Inner: StoreField<Value = Prev>,
550 Prev: 'static,
551 T: IndexMut<usize>,
552 T::Output: Sized,
553{
554 fn track(&self) {
555 self.track_field();
556 }
557}
558
559impl<Inner, Prev, K, T> ReadUntracked for AtKeyed<Inner, Prev, K, T>
560where
561 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
562 KeyedSubfield<Inner, Prev, K, T>: Clone,
563 for<'a> &'a T: IntoIterator,
564 Inner: StoreField<Value = Prev>,
565 Prev: 'static,
566 T: IndexMut<usize>,
567 T::Output: Sized,
568{
569 type Value = <Self as StoreField>::Reader;
570
571 fn try_read_untracked(&self) -> Option<Self::Value> {
572 self.reader()
573 }
574}
575
576impl<Inner, Prev, K, T> Write for AtKeyed<Inner, Prev, K, T>
577where
578 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
579 KeyedSubfield<Inner, Prev, K, T>: Clone,
580 for<'a> &'a T: IntoIterator,
581 Inner: StoreField<Value = Prev>,
582 Prev: 'static,
583 T: IndexMut<usize>,
584 T::Output: Sized + 'static,
585{
586 type Value = T::Output;
587
588 fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
589 self.writer()
590 }
591
592 fn try_write_untracked(
593 &self,
594 ) -> Option<impl DerefMut<Target = Self::Value>> {
595 self.writer().map(|mut writer| {
596 writer.untrack();
597 writer
598 })
599 }
600}
601
602impl<Inner, Prev, K, T> KeyedSubfield<Inner, Prev, K, T>
603where
604 Self: Clone,
605 for<'a> &'a T: IntoIterator,
606 Inner: StoreField<Value = Prev>,
607 Prev: 'static,
608 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
609{
610 pub fn update_keys(&self) {
612 let inner_path = self.path().into_iter().collect();
613 let keys = self
614 .inner
615 .keys()
616 .expect("updating keys on a store with no keys");
617
618 let latest = self.latest_keys();
623 keys.with_field_keys(
624 inner_path,
625 |keys| {
626 keys.update(latest);
627 },
628 || self.latest_keys(),
629 );
630 }
631}
632
633impl<Inner, Prev, K, T> IntoIterator for KeyedSubfield<Inner, Prev, K, T>
634where
635 Self: Clone,
636 for<'a> &'a T: IntoIterator,
637 Inner: Clone + StoreField<Value = Prev> + 'static,
638 Prev: 'static,
639 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
640 T: IndexMut<usize> + 'static,
641 T::Output: Sized,
642{
643 type Item = AtKeyed<Inner, Prev, K, T>;
644 type IntoIter = StoreFieldKeyedIter<Inner, Prev, K, T>;
645
646 #[track_caller]
647 fn into_iter(self) -> StoreFieldKeyedIter<Inner, Prev, K, T> {
648 self.update_keys();
650 self.track_field();
651
652 let reader = self.reader();
654
655 let keys = reader
656 .map(|r| {
657 r.into_iter()
658 .map(|item| (self.key_fn)(item))
659 .collect::<VecDeque<_>>()
660 })
661 .unwrap_or_default();
662
663 StoreFieldKeyedIter { inner: self, keys }
665 }
666}
667
668pub struct StoreFieldKeyedIter<Inner, Prev, K, T>
670where
671 for<'a> &'a T: IntoIterator,
672 T: IndexMut<usize>,
673{
674 inner: KeyedSubfield<Inner, Prev, K, T>,
675 keys: VecDeque<K>,
676}
677
678impl<Inner, Prev, K, T> Iterator for StoreFieldKeyedIter<Inner, Prev, K, T>
679where
680 Inner: StoreField<Value = Prev> + Clone + 'static,
681 T: IndexMut<usize> + 'static,
682 T::Output: Sized + 'static,
683 for<'a> &'a T: IntoIterator,
684{
685 type Item = AtKeyed<Inner, Prev, K, T>;
686
687 fn next(&mut self) -> Option<Self::Item> {
688 self.keys
689 .pop_front()
690 .map(|key| AtKeyed::new(self.inner.clone(), key))
691 }
692}
693
694impl<Inner, Prev, K, T> DoubleEndedIterator
695 for StoreFieldKeyedIter<Inner, Prev, K, T>
696where
697 Inner: StoreField<Value = Prev> + Clone + 'static,
698 T: IndexMut<usize> + 'static,
699 T::Output: Sized + 'static,
700 for<'a> &'a T: IntoIterator,
701{
702 fn next_back(&mut self) -> Option<Self::Item> {
703 self.keys
704 .pop_back()
705 .map(|key| AtKeyed::new(self.inner.clone(), key))
706 }
707}