1use crate::id::Id as RawId;
8use crate::{AnyView, View};
9use alloc::fmt::Debug;
10use alloc::{boxed::Box, collections::BTreeMap, rc::Rc, vec::Vec};
11use core::any::type_name;
12use core::num::NonZeroI32;
13use core::ops::{Bound, RangeBounds};
14use core::{
15 cell::{Cell, RefCell},
16 hash::Hash,
17};
18use nami::collection::Collection;
19use nami::watcher::{BoxWatcherGuard, Context, WatcherGuard};
20
21use crate::id::{Identifiable, SelfId};
22
23pub trait Views {
29 type Id: 'static + Hash + Ord + Clone;
32 type Guard: WatcherGuard;
34 type View: View;
36 fn get_id(&self, index: usize) -> Option<Self::Id>;
38 fn len(&self) -> usize;
40
41 fn is_empty(&self) -> bool {
43 self.len() == 0
44 }
45
46 fn watch(
50 &self,
51 range: impl RangeBounds<usize>,
52 watcher: impl for<'a> Fn(Context<&'a [Self::Id]>) + 'static, ) -> Self::Guard;
54
55 fn get_view(&self, id: usize) -> Option<Self::View>;
57}
58
59pub struct AnyViews<V>(Box<dyn AnyViewsImpl<View = V>>);
65
66impl<V> Debug for AnyViews<V> {
67 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
68 f.write_str(type_name::<Self>())
69 }
70}
71
72pub struct SharedAnyViews<V>(Rc<dyn AnyViewsImpl<View = V>>);
76
77impl<V> Clone for SharedAnyViews<V> {
78 fn clone(&self) -> Self {
79 Self(self.0.clone())
80 }
81}
82
83impl<V> SharedAnyViews<V> {
84 pub fn new(contents: impl Views<View = V> + 'static) -> Self {
95 Self(Rc::new(IntoAnyViews::new(contents)))
96 }
97}
98
99impl<V> From<AnyViews<V>> for SharedAnyViews<V> {
100 fn from(value: AnyViews<V>) -> Self {
101 Self(Rc::from(value.0))
102 }
103}
104
105impl<V> Debug for SharedAnyViews<V> {
106 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
107 f.write_str(type_name::<Self>())
108 }
109}
110
111impl<V: View> Views for SharedAnyViews<V> {
112 type Id = SelfId<RawId>;
113 type Guard = BoxWatcherGuard;
114 type View = V;
115 fn get_id(&self, index: usize) -> Option<Self::Id> {
116 self.0.get_id(index).map(SelfId::new)
117 }
118 fn get_view(&self, index: usize) -> Option<Self::View> {
119 self.0.get_view(index)
120 }
121 fn len(&self) -> usize {
122 self.0.len()
123 }
124
125 fn watch(
126 &self,
127 range: impl RangeBounds<usize>,
128 watcher: impl for<'a> Fn(Context<&'a [Self::Id]>) + 'static, ) -> Self::Guard {
130 self.0.watch(
131 (range.start_bound().cloned(), range.end_bound().cloned()),
132 Box::new(move |ctx| {
133 let ctx =
134 ctx.map(|value| value.iter().copied().map(SelfId::new).collect::<Vec<_>>());
135 watcher(ctx.as_deref());
136 }),
137 )
138 }
139}
140
141trait AnyViewsImpl {
142 type View;
143
144 fn get_view(&self, index: usize) -> Option<Self::View>;
145 fn get_id(&self, index: usize) -> Option<RawId>;
146 fn len(&self) -> usize;
147 #[allow(clippy::type_complexity)]
148 fn watch(
149 &self,
150 range: (Bound<usize>, Bound<usize>),
151 watcher: Box<dyn for<'a> Fn(Context<&'a [RawId]>) + 'static>,
152 ) -> BoxWatcherGuard;
153}
154
155#[derive(Debug)]
156struct IdGenerator<Id> {
157 map: RefCell<BTreeMap<Id, i32>>,
158 counter: Cell<i32>,
159}
160
161impl<Id: Hash + Ord> Default for IdGenerator<Id> {
162 fn default() -> Self {
163 Self::new()
164 }
165}
166
167impl<Id: Hash + Ord> IdGenerator<Id> {
168 pub const fn new() -> Self {
169 Self {
170 map: RefCell::new(BTreeMap::new()),
171 counter: Cell::new(i32::MIN),
172 }
173 }
174 pub fn to_id(&self, value: Id) -> RawId {
175 let mut this = self.map.borrow_mut();
176 if let Some(&id) = this.get(&value) {
177 return RawId::from(unsafe { NonZeroI32::new_unchecked(id) });
178 }
179 let id = self.counter.get();
180 self.counter
181 .set(id.checked_add(1).expect("id counter should not overflow"));
182 this.insert(value, id);
183 RawId::from(unsafe { NonZeroI32::new_unchecked(id) })
184 }
185}
186
187struct IntoAnyViews<V>
188where
189 V: Views,
190{
191 contents: V,
192 id: Rc<IdGenerator<V::Id>>,
193}
194
195impl<V> IntoAnyViews<V>
196where
197 V: Views + 'static,
198{
199 pub fn new(contents: V) -> Self {
200 Self {
201 contents,
202 id: Rc::default(),
203 }
204 }
205}
206
207impl<V> AnyViewsImpl for IntoAnyViews<V>
208where
209 V: Views + 'static,
210{
211 type View = V::View;
212
213 fn get_view(&self, index: usize) -> Option<Self::View> {
214 self.contents.get_view(index)
215 }
216
217 fn get_id(&self, index: usize) -> Option<RawId> {
218 self.contents.get_id(index).map(|item| self.id.to_id(item))
219 }
220
221 fn len(&self) -> usize {
222 self.contents.len()
223 }
224
225 fn watch(
226 &self,
227 range: (Bound<usize>, Bound<usize>),
228 watcher: Box<dyn for<'a> Fn(Context<&'a [RawId]>) + 'static>,
229 ) -> BoxWatcherGuard {
230 let id = self.id.clone();
231 Box::new(self.contents.watch(range, move |ctx| {
232 let ctx = ctx.map(|value| {
233 value
234 .iter()
235 .map(|data| id.to_id(data.clone()))
236 .collect::<Vec<_>>()
237 });
238 watcher(ctx.as_deref());
239 }))
240 }
241}
242impl<V> AnyViews<V>
243where
244 V: View,
245{
246 pub fn new<C>(contents: C) -> Self
257 where
258 C: Views<View = V> + 'static,
259 {
260 Self(Box::new(IntoAnyViews {
261 id: Rc::new(IdGenerator::<C::Id>::new()),
262 contents,
263 }))
264 }
265}
266
267impl<V> Views for AnyViews<V>
268where
269 V: View,
270{
271 type Id = SelfId<RawId>;
272 type Guard = BoxWatcherGuard;
273 type View = V;
274 fn get_id(&self, index: usize) -> Option<Self::Id> {
275 self.0.get_id(index).map(SelfId::new)
276 }
277 fn get_view(&self, index: usize) -> Option<Self::View> {
278 self.0.get_view(index)
279 }
280 fn len(&self) -> usize {
281 self.0.len()
282 }
283
284 fn watch(
285 &self,
286 range: impl RangeBounds<usize>,
287 watcher: impl for<'a> Fn(Context<&'a [Self::Id]>) + 'static, ) -> Self::Guard {
289 self.0.watch(
290 (range.start_bound().cloned(), range.end_bound().cloned()),
291 Box::new(move |ctx| {
292 let ctx =
293 ctx.map(|value| value.iter().copied().map(SelfId::new).collect::<Vec<_>>());
294 watcher(ctx.as_deref());
295 }),
296 )
297 }
298}
299#[derive(Debug, Clone)]
305pub struct ForEach<C, F, V>
306where
307 C: Collection,
308 C::Item: Identifiable,
309 F: Fn(C::Item) -> V,
310 V: View,
311{
312 data: C,
313 generator: F,
314}
315
316impl<C, F, V> ForEach<C, F, V>
317where
318 C: Collection,
319 C::Item: Identifiable,
320 F: Fn(C::Item) -> V,
321 V: View,
322{
323 pub const fn new(data: C, generator: F) -> Self {
332 Self { data, generator }
333 }
334
335 pub fn into_inner(self) -> (C, F) {
340 (self.data, self.generator)
341 }
342}
343
344#[derive(Debug)]
346#[allow(dead_code)]
347pub struct ForEachItem<T, F, V>
348where
349 F: Fn(T) -> V,
350 V: View,
351{
352 data: T,
353
354 generator: Rc<F>,
355}
356
357impl<C, F, V> Collection for ForEach<C, F, V>
358where
359 C: Collection,
360 C::Item: Identifiable,
361 F: 'static + Fn(C::Item) -> V,
362 V: View,
363{
364 type Item = <C::Item as Identifiable>::Id;
365 type Guard = C::Guard;
366 fn get(&self, index: usize) -> Option<Self::Item> {
367 self.data.get(index).map(|item| item.id())
368 }
369
370 fn len(&self) -> usize {
371 self.data.len()
372 }
373
374 fn watch(
375 &self,
376 range: impl RangeBounds<usize>,
377 watcher: impl for<'a> Fn(Context<&'a [Self::Item]>) + 'static, ) -> Self::Guard {
379 self.data.watch(range, move |ctx| {
380 let ctx = ctx.map(|value| {
381 value
382 .iter()
383 .map(super::id::Identifiable::id)
384 .collect::<Vec<_>>()
385 });
386
387 watcher(ctx.as_deref());
388 })
389 }
390}
391
392impl<C, F, V> Views for ForEach<C, F, V>
393where
394 C: Collection,
395 C::Item: Identifiable,
396 F: 'static + Fn(C::Item) -> V,
397 V: View,
398{
399 type Id = <C::Item as Identifiable>::Id;
400 type View = V;
401 type Guard = C::Guard;
402 fn get_id(&self, index: usize) -> Option<Self::Id> {
403 self.data.get(index).map(|item| item.id())
404 }
405 fn get_view(&self, index: usize) -> Option<Self::View> {
406 self.data.get(index).map(|item| (self.generator)(item))
407 }
408 fn len(&self) -> usize {
409 self.data.len()
410 }
411 fn watch(
412 &self,
413 range: impl RangeBounds<usize>,
414 watcher: impl for<'a> Fn(Context<&'a [Self::Id]>) + 'static, ) -> Self::Guard {
416 self.data.watch(range, move |ctx| {
417 let ctx = ctx.map(|value| {
418 value
419 .iter()
420 .map(super::id::Identifiable::id)
421 .collect::<Vec<_>>()
422 });
423
424 watcher(ctx.as_deref());
425 })
426 }
427}
428
429#[derive(Debug, Clone)]
435pub struct Constant<C>
436where
437 C: Collection,
438 C::Item: View,
439{
440 value: C,
441}
442
443impl<C> Constant<C>
444where
445 C: Collection,
446 C::Item: View,
447{
448 pub const fn new(value: C) -> Self {
456 Self { value }
457 }
458}
459
460impl<C> Collection for Constant<C>
461where
462 C: Collection + Clone,
463 C::Item: View,
464{
465 type Item = SelfId<usize>;
466 type Guard = ();
467
468 fn get(&self, index: usize) -> Option<Self::Item> {
469 if index < self.value.len() {
470 Some(SelfId::new(index))
471 } else {
472 None
473 }
474 }
475
476 fn len(&self) -> usize {
477 self.value.len()
478 }
479
480 fn watch(
481 &self,
482 _range: impl RangeBounds<usize>,
483 _watcher: impl for<'a> Fn(Context<&'a [Self::Item]>) + 'static, ) -> Self::Guard {
485 }
486}
487
488impl<V> Views for Constant<V>
489where
490 V: Collection + Clone,
491 V::Item: View,
492{
493 type Id = SelfId<usize>;
494 type Guard = ();
495 type View = V::Item;
496
497 fn len(&self) -> usize {
498 self.value.len()
499 }
500
501 fn get_id(&self, index: usize) -> Option<Self::Id> {
502 if index < self.value.len() {
503 Some(SelfId::new(index))
504 } else {
505 None
506 }
507 }
508
509 fn get_view(&self, index: usize) -> Option<Self::View> {
510 self.value.get(index)
511 }
512
513 fn watch(
514 &self,
515 _range: impl RangeBounds<usize>,
516 _watcher: impl for<'a> Fn(Context<&'a [Self::Id]>) + 'static, ) -> Self::Guard {
518 }
520}
521
522impl<V: View + Clone> Views for Vec<V> {
523 type Id = SelfId<usize>;
524 type Guard = ();
525 type View = V;
526
527 fn len(&self) -> usize {
528 self.len()
529 }
530
531 fn get_id(&self, index: usize) -> Option<Self::Id> {
532 if index < self.len() {
533 Some(SelfId::new(index))
534 } else {
535 None
536 }
537 }
538
539 fn get_view(&self, index: usize) -> Option<Self::View> {
540 self.get(index)
541 }
542
543 fn watch(
544 &self,
545 _range: impl RangeBounds<usize>,
546 _watcher: impl for<'a> Fn(Context<&'a [Self::Id]>) + 'static, ) -> Self::Guard {
548 }
550}
551
552impl<V: View + Clone, const N: usize> Views for [V; N] {
553 type Id = SelfId<usize>;
554 type Guard = ();
555 type View = V;
556
557 fn len(&self) -> usize {
558 self.as_ref().len()
559 }
560
561 fn get_id(&self, index: usize) -> Option<Self::Id> {
562 if index < self.as_ref().len() {
563 Some(SelfId::new(index))
564 } else {
565 None
566 }
567 }
568
569 fn get_view(&self, index: usize) -> Option<Self::View> {
570 self.get(index)
571 }
572
573 fn watch(
574 &self,
575 _range: impl RangeBounds<usize>,
576 _watcher: impl for<'a> Fn(Context<&'a [Self::Id]>) + 'static, ) -> Self::Guard {
578 }
580}
581
582#[derive(Debug, Clone)]
587pub struct Map<C, F> {
588 source: C,
589 f: F,
590}
591
592impl<C, F, V> Map<C, F>
593where
594 C: Views,
595 F: Fn(C::View) -> V,
596 V: View,
597{
598 #[must_use]
607 pub const fn new(source: C, f: F) -> Self {
608 Self { source, f }
609 }
610}
611
612impl<C, F, V> Views for Map<C, F>
613where
614 C: Views,
615 F: Clone + Fn(C::View) -> V,
616 V: View,
617{
618 type Id = C::Id;
619 type Guard = C::Guard;
620 type View = V;
621
622 fn len(&self) -> usize {
623 self.source.len()
624 }
625
626 fn get_id(&self, index: usize) -> Option<Self::Id> {
627 self.source.get_id(index)
628 }
629
630 fn get_view(&self, index: usize) -> Option<Self::View> {
631 self.source.get_view(index).map(&self.f)
632 }
633
634 fn watch(
635 &self,
636 range: impl RangeBounds<usize>,
637 watcher: impl for<'a> Fn(Context<&'a [Self::Id]>) + 'static, ) -> Self::Guard {
639 self.source.watch(range, watcher)
640 }
641}
642
643pub trait ViewsExt: Views {
648 fn map<F, V>(self, f: F) -> Map<Self, F>
656 where
657 Self: Sized,
658 F: Fn(Self::View) -> V,
659 V: View,
660 {
661 Map::new(self, f)
662 }
663
664 fn erase(self) -> AnyViews<AnyView>
666 where
667 Self: 'static + Sized,
668 {
669 AnyViews::new(self.map(AnyView::new))
670 }
671}
672
673impl<T: Views> ViewsExt for T {}