1use std::ops;
2
3use crate::{VARS, VarUpdateId, VarValue};
4
5#[derive(Debug, Clone, PartialEq)]
20pub struct ObservableVec<T: VarValue> {
21 list: Vec<T>,
22 changes: VecChanges,
23}
24impl<T: VarValue> Default for ObservableVec<T> {
25 fn default() -> Self {
26 Self::new()
27 }
28}
29impl<T: VarValue> ops::Deref for ObservableVec<T> {
30 type Target = [T];
31
32 fn deref(&self) -> &Self::Target {
33 self.list.deref()
34 }
35}
36impl<T: VarValue> ObservableVec<T> {
37 pub const fn new() -> Self {
39 Self {
40 list: vec![],
41 changes: VecChanges::new(),
42 }
43 }
44
45 pub fn with_capacity(capacity: usize) -> Self {
49 Self {
50 list: Vec::with_capacity(capacity),
51 changes: VecChanges::new(),
52 }
53 }
54
55 pub fn reserve(&mut self, additional: usize) {
59 self.list.reserve(additional);
60 }
61
62 pub fn insert(&mut self, index: usize, element: T) {
66 self.list.insert(index, element);
67 self.changes.inserted(index, 1);
68 }
69
70 pub fn push(&mut self, element: T) {
74 self.insert(self.len(), element);
75 }
76
77 pub fn append(&mut self, other: &mut Vec<T>) {
81 self.changes.inserted(self.list.len(), other.len());
82 self.list.append(other);
83 }
84
85 pub fn remove(&mut self, index: usize) -> T {
89 let r = self.list.remove(index);
90 self.changes.removed(index, 1);
91 r
92 }
93
94 pub fn pop(&mut self) -> Option<T> {
98 if self.is_empty() { None } else { Some(self.remove(self.len() - 1)) }
99 }
100
101 pub fn truncate(&mut self, len: usize) {
105 if len < self.len() {
106 let count = self.len() - len;
107 self.changes.removed(len, count);
108 }
109 self.list.truncate(len);
110 }
111
112 pub fn swap_remove(&mut self, index: usize) -> T {
116 let r = self.list.swap_remove(index);
117
118 self.changes.removed(index, 1);
119 self.changes.moved(self.list.len() - 1, index);
120
121 r
122 }
123
124 pub fn clear(&mut self) {
128 if !self.is_empty() {
129 self.clear();
130 self.changes.cleared();
131 }
132 }
133
134 pub fn retain<F>(&mut self, mut f: F)
138 where
139 F: FnMut(&mut T) -> bool,
140 {
141 let mut i = 0;
142
143 self.list.retain_mut(|it| {
144 let retain = f(it);
145 if retain {
146 i += 1;
147 } else {
148 self.changes.removed(i, 1);
149 }
150 retain
151 })
152 }
153
154 pub fn drain<R>(&mut self, range: R) -> std::vec::Drain<'_, T>
158 where
159 R: ops::RangeBounds<usize>,
160 {
161 let range = std_slice_range(range, ..self.len());
162 let r = self.list.drain(range.clone());
163
164 if !range.is_empty() {
165 self.changes.removed(range.start, range.len());
166 }
167
168 r
169 }
170
171 pub fn resize(&mut self, new_len: usize, value: T) {
175 if new_len <= self.len() {
176 self.truncate(new_len);
177 } else {
178 let count = new_len - self.len();
179 self.changes.inserted(self.len(), count);
180 self.list.resize(new_len, value);
181 }
182 }
183
184 pub fn extend_from_slice(&mut self, other: &[T]) {
188 if !other.is_empty() {
189 self.changes.inserted(self.len(), other.len());
190 }
191 self.list.extend_from_slice(other);
192 }
193
194 pub fn extend_from_within<R>(&mut self, src: R)
196 where
197 R: ops::RangeBounds<usize>,
198 {
199 let src = std_slice_range(src, ..self.len());
200
201 let index = self.len();
202
203 self.list.extend_from_within(src.clone());
204
205 if !src.is_empty() {
206 self.changes.inserted(index, src.len());
207 }
208 }
209
210 pub fn reinsert(&mut self, from: usize, mut to: usize) {
216 if from != to {
217 if from < to {
218 to -= 1;
219 }
220 let el = self.list.remove(from);
221 self.list.insert(to, el);
222 self.changes.moved(from, to);
223 } else {
224 let _ = &self.list[to];
226 }
227 }
228
229 pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
233 let r = self.list.get_mut(index);
234 if r.is_some() {
235 self.changes.removed(index, 1);
236 self.changes.inserted(index, 1);
237 }
238 r
239 }
240
241 pub fn slice_mut<R>(&mut self, range: R) -> &mut [T]
245 where
246 R: ops::RangeBounds<usize>,
247 {
248 let range = std_slice_range(range, ..self.len());
249 let r = &mut self.list[range.clone()];
250
251 let count = range.len();
252 if count > 0 {
253 self.changes.removed(range.start, count);
254 self.changes.inserted(range.start, count);
255 }
256
257 r
258 }
259
260 pub fn changes(&self) -> &[VecChange] {
264 if self.changes.update_id == VARS.update_id() {
265 &self.changes.changes
266 } else {
267 &[]
268 }
269 }
270}
271
272impl<T: VarValue> Extend<T> for ObservableVec<T> {
273 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
274 let index = self.len();
275 self.list.extend(iter);
276 let count = self.len() - index;
277 if count > 0 {
278 self.changes.inserted(index, count);
279 }
280 }
281}
282impl<T: VarValue> From<Vec<T>> for ObservableVec<T> {
283 fn from(value: Vec<T>) -> Self {
284 Self {
285 list: value,
286 changes: VecChanges::new(),
287 }
288 }
289}
290impl<T: VarValue> From<ObservableVec<T>> for Vec<T> {
291 fn from(value: ObservableVec<T>) -> Self {
292 value.list
293 }
294}
295
296#[derive(Clone, Copy, Debug, PartialEq, Eq)]
298pub enum VecChange {
299 Remove {
301 index: usize,
303 count: usize,
305 },
306 Insert {
308 index: usize,
314 count: usize,
316 },
317 Move {
319 from_index: usize,
321 to_index: usize,
323 },
324 Clear,
326}
327
328#[derive(Debug, PartialEq)]
329struct VecChanges {
330 changes: Vec<VecChange>,
331 update_id: VarUpdateId,
332}
333impl Clone for VecChanges {
334 fn clone(&self) -> Self {
335 let update_id = VARS.update_id();
336 if self.update_id == update_id {
337 Self {
338 changes: self.changes.clone(),
339 update_id,
340 }
341 } else {
342 Self {
343 changes: vec![],
344 update_id,
345 }
346 }
347 }
348}
349impl VecChanges {
350 const fn new() -> Self {
351 Self {
352 changes: vec![],
353 update_id: VarUpdateId::never(),
354 }
355 }
356
357 pub fn inserted(&mut self, i: usize, n: usize) {
358 let update_id = VARS.update_id();
359 if self.update_id != update_id {
360 self.changes.clear();
361 self.changes.push(VecChange::Insert { index: i, count: n });
362 self.update_id = update_id;
363 } else if self.changes != [VecChange::Clear] {
364 if let Some(VecChange::Insert { index, count }) = self.changes.last_mut() {
365 if i >= *index && i <= *index + *count {
366 *count += n;
368 return;
369 } else {
370 self.changes.clear();
372 self.changes.push(VecChange::Clear);
373 return;
374 }
375 }
376 self.changes.push(VecChange::Insert { index: i, count: n });
377 }
378 }
379
380 pub fn moved(&mut self, f: usize, t: usize) {
381 let update_id = VARS.update_id();
382 if self.update_id != update_id {
383 self.changes.clear();
384 self.changes.push(VecChange::Move {
385 from_index: f,
386 to_index: t,
387 });
388 self.update_id = update_id;
389 } else if self.changes != [VecChange::Clear] {
390 self.changes.push(VecChange::Move {
391 from_index: f,
392 to_index: t,
393 });
394 }
395 }
396
397 pub fn removed(&mut self, i: usize, n: usize) {
398 let update_id = VARS.update_id();
399 if self.update_id != update_id {
400 self.changes.clear();
401 self.changes.push(VecChange::Remove { index: i, count: n });
402 self.update_id = update_id;
403 } else if self.changes != [VecChange::Clear] {
404 if let Some(last) = self.changes.last_mut() {
405 match last {
406 VecChange::Remove { index, count } => {
407 let s = i;
408 let e = i + n;
409
410 if s <= *index && e > *index {
411 *index = s;
413 *count += n;
414 return;
415 }
416 }
417 VecChange::Insert { .. } => {
418 self.changes.clear();
420 self.changes.push(VecChange::Clear);
421 return;
422 }
423 _ => {}
424 }
425 }
426
427 self.changes.push(VecChange::Remove { index: i, count: n });
428 }
429 }
430
431 pub fn cleared(&mut self) {
432 self.changes.clear();
433 self.changes.push(VecChange::Clear);
434 self.update_id = VARS.update_id();
435 }
436}
437
438#[track_caller]
440#[must_use]
441fn std_slice_range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
442where
443 R: ops::RangeBounds<usize>,
444{
445 let len = bounds.end;
446
447 let start: ops::Bound<&usize> = range.start_bound();
448 let start = match start {
449 ops::Bound::Included(&start) => start,
450 ops::Bound::Excluded(start) => start.checked_add(1).unwrap(),
451 ops::Bound::Unbounded => 0,
452 };
453
454 let end: ops::Bound<&usize> = range.end_bound();
455 let end = match end {
456 ops::Bound::Included(end) => end.checked_add(1).unwrap(),
457 ops::Bound::Excluded(&end) => end,
458 ops::Bound::Unbounded => len,
459 };
460
461 if start > end {
462 panic!("invalid range {start}..{end}");
463 }
464 if end > len {
465 panic!("invalid range {start}..{end}");
466 }
467
468 ops::Range { start, end }
469}