1pub trait Collection: Clone + 'static {
6 type Item: 'static;
8 type Guard: WatcherGuard;
10
11 fn get(&self, index: usize) -> Option<Self::Item>;
13 fn len(&self) -> usize;
15
16 fn is_empty(&self) -> bool {
18 self.len() == 0
19 }
20
21 fn watch(
25 &self,
26 range: impl RangeBounds<usize>,
27 watcher: impl for<'a> Fn(Context<&'a [Self::Item]>) + 'static, ) -> Self::Guard;
29}
30
31use core::ops::{Bound, RangeBounds};
32
33use alloc::{boxed::Box, vec::Vec};
34
35use crate::watcher::{BoxWatcherGuard, Context, WatcherGuard};
36
37impl<T: Clone + 'static> Collection for Vec<T> {
38 type Item = T;
39 type Guard = ();
40
41 fn get(&self, index: usize) -> Option<Self::Item> {
42 self.as_slice().get(index).cloned()
43 }
44 fn len(&self) -> usize {
45 <[T]>::len(self)
46 }
47 fn watch(
48 &self,
49 _range: impl RangeBounds<usize>,
50 _watcher: impl for<'a> Fn(Context<&'a [Self::Item]>) + 'static,
51 ) -> Self::Guard {
52 }
54}
55
56impl<T: Clone + 'static> Collection for &'static [T] {
57 type Item = T;
58 type Guard = ();
59
60 fn get(&self, index: usize) -> Option<Self::Item> {
61 (*self).get(index).cloned()
62 }
63 fn len(&self) -> usize {
64 <[T]>::len(self)
65 }
66 fn watch(
67 &self,
68 _range: impl RangeBounds<usize>,
69 _watcher: impl for<'a> Fn(Context<&'a [Self::Item]>) + 'static,
70 ) -> Self::Guard {
71 }
73}
74
75impl<T: Clone + 'static, const N: usize> Collection for [T; N] {
76 type Item = T;
77 type Guard = ();
78
79 fn get(&self, index: usize) -> Option<Self::Item> {
80 self.as_slice().get(index).cloned()
81 }
82 fn len(&self) -> usize {
83 N
84 }
85 fn watch(
86 &self,
87 _range: impl RangeBounds<usize>,
88 _watcher: impl for<'a> Fn(Context<&'a [Self::Item]>) + 'static,
89 ) -> Self::Guard {
90 }
91}
92
93pub struct AnyCollection<T> {
99 inner: Box<dyn AnyCollectionImpl<Output = T>>,
100}
101
102impl<T> core::fmt::Debug for AnyCollection<T> {
103 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
104 f.debug_struct("AnyCollection").finish()
105 }
106}
107impl<T> Clone for AnyCollection<T> {
108 fn clone(&self) -> Self {
109 Self {
110 inner: self.inner.clone(),
111 }
112 }
113}
114
115pub type BoxCollectionWatcher<T> = Box<dyn for<'a> Fn(Context<&'a [T]>) + 'static>;
117
118trait AnyCollectionImpl {
120 type Output;
121 fn get(&self, index: usize) -> Option<Self::Output>;
122 fn len(&self) -> usize;
123 fn is_empty(&self) -> bool;
124 fn watch(
125 &self,
126 range: (Bound<usize>, Bound<usize>),
127 watcher: BoxCollectionWatcher<Self::Output>,
128 ) -> BoxWatcherGuard;
129 fn clone(&self) -> Box<dyn AnyCollectionImpl<Output = Self::Output>>;
130}
131
132impl<T> AnyCollectionImpl for T
133where
134 T: Collection,
135{
136 type Output = T::Item;
137 fn get(&self, index: usize) -> Option<Self::Output> {
138 <T as Collection>::get(self, index)
139 }
140
141 fn len(&self) -> usize {
142 <T as Collection>::len(self)
143 }
144
145 fn is_empty(&self) -> bool {
146 <T as Collection>::is_empty(self)
147 }
148
149 fn watch(
150 &self,
151 range: (Bound<usize>, Bound<usize>),
152 watcher: Box<dyn for<'a> Fn(Context<&'a [Self::Output]>) + 'static>,
153 ) -> BoxWatcherGuard {
154 Box::new(<T as Collection>::watch(self, range, watcher))
155 }
156
157 fn clone(&self) -> Box<dyn AnyCollectionImpl<Output = Self::Output>> {
158 Box::new(self.clone())
159 }
160}
161
162impl<T> AnyCollection<T> {
163 pub fn new<C>(collection: C) -> Self
165 where
166 C: Collection<Item = T>,
167 {
168 Self {
169 inner: Box::new(collection),
170 }
171 }
172
173 #[must_use]
178 pub fn get(&self, index: usize) -> Option<T> {
179 self.inner.get(index)
180 }
181
182 #[must_use]
184 pub fn len(&self) -> usize {
185 self.inner.len()
186 }
187
188 #[must_use]
190 pub fn is_empty(&self) -> bool {
191 self.inner.is_empty()
192 }
193
194 pub fn watch(
199 &self,
200 range: impl RangeBounds<usize>,
201 watcher: impl for<'a> Fn(Context<&'a [T]>) + 'static,
202 ) -> BoxWatcherGuard {
203 let start_bound = match range.start_bound() {
204 Bound::Included(&n) => Bound::Included(n),
205 Bound::Excluded(&n) => Bound::Excluded(n),
206 Bound::Unbounded => Bound::Unbounded,
207 };
208 let end_bound = match range.end_bound() {
209 Bound::Included(&n) => Bound::Included(n),
210 Bound::Excluded(&n) => Bound::Excluded(n),
211 Bound::Unbounded => Bound::Unbounded,
212 };
213
214 self.inner
215 .watch((start_bound, end_bound), Box::new(watcher))
216 }
217}