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