eyeball_im_util/vector/sort.rs
1use std::{
2 cmp::Ordering,
3 ops::Not,
4 pin::Pin,
5 task::{self, ready, Poll},
6};
7
8use eyeball_im::{Vector, VectorDiff};
9use futures_core::Stream;
10use pin_project_lite::pin_project;
11use smallvec::SmallVec;
12
13use super::{
14 VectorDiffContainer, VectorDiffContainerOps, VectorDiffContainerStreamElement,
15 VectorDiffContainerStreamSortBuf,
16};
17
18type UnsortedIndex = usize;
19
20pin_project! {
21 /// A [`VectorDiff`] stream adapter that presents a sorted view of the
22 /// underlying [`ObservableVector`] items.
23 ///
24 /// ```rust
25 /// use eyeball_im::{ObservableVector, VectorDiff};
26 /// use eyeball_im_util::vector::VectorObserverExt;
27 /// use imbl::vector;
28 /// use stream_assert::{assert_closed, assert_next_eq, assert_pending};
29 ///
30 /// // Our vector.
31 /// let mut ob = ObservableVector::<char>::new();
32 /// let (values, mut sub) = ob.subscribe().sort();
33 ///
34 /// assert!(values.is_empty());
35 /// assert_pending!(sub);
36 ///
37 /// // Append multiple unsorted values.
38 /// ob.append(vector!['d', 'b', 'e']);
39 /// // We get a `VectorDiff::Append` with sorted values!
40 /// assert_next_eq!(sub, VectorDiff::Append { values: vector!['b', 'd', 'e'] });
41 ///
42 /// // Let's recap what we have. `ob` is our `ObservableVector`,
43 /// // `sub` is the “sorted view” / “sorted stream” of `ob`:
44 /// // | `ob` | d b e |
45 /// // | `sub` | b d e |
46 ///
47 /// // Append multiple other values.
48 /// ob.append(vector!['f', 'g', 'a', 'c']);
49 /// // We get three `VectorDiff`s!
50 /// assert_next_eq!(sub, VectorDiff::PushFront { value: 'a' });
51 /// assert_next_eq!(sub, VectorDiff::Insert { index: 2, value: 'c' });
52 /// assert_next_eq!(sub, VectorDiff::Append { values: vector!['f', 'g'] });
53 ///
54 /// // Let's recap what we have:
55 /// // | `ob` | d b e f g a c |
56 /// // | `sub` | a b c d e f g |
57 /// // ^ ^ ^^^
58 /// // | | |
59 /// // | | with `VectorDiff::Append { .. }`
60 /// // | with `VectorDiff::Insert { index: 2, .. }`
61 /// // with `VectorDiff::PushFront { .. }`
62 ///
63 /// // Technically, `Sort` emits `VectorDiff`s that mimic a sorted `Vector`.
64 ///
65 /// drop(ob);
66 /// assert_closed!(sub);
67 /// ```
68 ///
69 /// [`ObservableVector`]: eyeball_im::ObservableVector
70 pub struct Sort<S>
71 where
72 S: Stream,
73 S::Item: VectorDiffContainer,
74 {
75 #[pin]
76 inner: SortImpl<S>,
77 }
78}
79
80impl<S> Sort<S>
81where
82 S: Stream,
83 S::Item: VectorDiffContainer,
84 VectorDiffContainerStreamElement<S>: Ord,
85{
86 /// Create a new `Sort` with the given (unsorted) initial values and stream
87 /// of `VectorDiff` updates for those values.
88 pub fn new(
89 initial_values: Vector<VectorDiffContainerStreamElement<S>>,
90 inner_stream: S,
91 ) -> (Vector<VectorDiffContainerStreamElement<S>>, Self) {
92 let (initial_sorted, inner) = SortImpl::new(initial_values, inner_stream, Ord::cmp);
93 (initial_sorted, Self { inner })
94 }
95}
96
97impl<S> Stream for Sort<S>
98where
99 S: Stream,
100 S::Item: VectorDiffContainer,
101 VectorDiffContainerStreamElement<S>: Ord,
102{
103 type Item = S::Item;
104
105 fn poll_next(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> {
106 self.project().inner.poll_next(cx, Ord::cmp)
107 }
108}
109
110pin_project! {
111 /// A [`VectorDiff`] stream adapter that presents a sorted view of the
112 /// underlying [`ObservableVector`] items.
113 ///
114 /// Sorting is done using a custom comparison function. Otherwise this
115 /// adapter works exactly like [`Sort`], see that type's documentation for
116 /// details on how this adapter operates.
117 ///
118 /// [`ObservableVector`]: eyeball_im::ObservableVector
119 pub struct SortBy<S, F>
120 where
121 S: Stream,
122 S::Item: VectorDiffContainer,
123 {
124 #[pin]
125 inner: SortImpl<S>,
126
127 // The comparison function to sort items.
128 compare: F,
129 }
130}
131
132impl<S, F> SortBy<S, F>
133where
134 S: Stream,
135 S::Item: VectorDiffContainer,
136 F: Fn(&VectorDiffContainerStreamElement<S>, &VectorDiffContainerStreamElement<S>) -> Ordering,
137{
138 /// Create a new `SortBy` with the given (unsorted) initial values, stream
139 /// of `VectorDiff` updates for those values, and the comparison function.
140 pub fn new(
141 initial_values: Vector<VectorDiffContainerStreamElement<S>>,
142 inner_stream: S,
143 compare: F,
144 ) -> (Vector<VectorDiffContainerStreamElement<S>>, Self) {
145 let (initial_sorted, inner) = SortImpl::new(initial_values, inner_stream, &compare);
146 (initial_sorted, Self { inner, compare })
147 }
148}
149
150impl<S, F> Stream for SortBy<S, F>
151where
152 S: Stream,
153 S::Item: VectorDiffContainer,
154 F: Fn(&VectorDiffContainerStreamElement<S>, &VectorDiffContainerStreamElement<S>) -> Ordering,
155{
156 type Item = S::Item;
157
158 fn poll_next(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> {
159 let this = self.project();
160 this.inner.poll_next(cx, &*this.compare)
161 }
162}
163
164pin_project! {
165 /// A [`VectorDiff`] stream adapter that presents a sorted view of the
166 /// underlying [`ObservableVector`] items.
167 ///
168 /// Sorting is done by transforming items to a key with a custom function
169 /// and comparing those. Otherwise this adapter works exactly like [`Sort`],
170 /// see that type's documentation for details on how this adapter operates.
171 ///
172 /// [`ObservableVector`]: eyeball_im::ObservableVector
173 pub struct SortByKey<S, F>
174 where
175 S: Stream,
176 S::Item: VectorDiffContainer,
177 {
178 #[pin]
179 inner: SortImpl<S>,
180
181 // The function to convert an item to a key used for comparison.
182 key_fn: F,
183 }
184}
185
186impl<S, F, K> SortByKey<S, F>
187where
188 S: Stream,
189 S::Item: VectorDiffContainer,
190 F: Fn(&VectorDiffContainerStreamElement<S>) -> K,
191 K: Ord,
192{
193 /// Create a new `SortByKey` with the given (unsorted) initial values,
194 /// stream of `VectorDiff` updates for those values, and the key function.
195 pub fn new(
196 initial_values: Vector<VectorDiffContainerStreamElement<S>>,
197 inner_stream: S,
198 key_fn: F,
199 ) -> (Vector<VectorDiffContainerStreamElement<S>>, Self) {
200 let (initial_sorted, inner) =
201 SortImpl::new(initial_values, inner_stream, |a, b| key_fn(a).cmp(&key_fn(b)));
202 (initial_sorted, Self { inner, key_fn })
203 }
204}
205
206impl<S, F, K> Stream for SortByKey<S, F>
207where
208 S: Stream,
209 S::Item: VectorDiffContainer,
210 F: Fn(&VectorDiffContainerStreamElement<S>) -> K,
211 K: Ord,
212{
213 type Item = S::Item;
214
215 fn poll_next(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> {
216 let this = self.project();
217 let key_fn = &*this.key_fn;
218 this.inner.poll_next(cx, |a, b| key_fn(a).cmp(&key_fn(b)))
219 }
220}
221
222pin_project! {
223 pub struct SortImpl<S>
224 where
225 S: Stream,
226 S::Item: VectorDiffContainer,
227 {
228 // The main stream to poll items from.
229 #[pin]
230 inner_stream: S,
231
232 // This is the **sorted** buffered vector.
233 buffered_vector: Vector<(UnsortedIndex, VectorDiffContainerStreamElement<S>)>,
234
235 // This adapter can produce many items per item of the underlying stream.
236 //
237 // Thus, if the item type is just `VectorDiff<_>` (non-bached, can't
238 // just add diffs to a `poll_next` result), we need a buffer to store the
239 // possible extra items in.
240 ready_values: VectorDiffContainerStreamSortBuf<S>,
241 }
242}
243
244impl<S> SortImpl<S>
245where
246 S: Stream,
247 S::Item: VectorDiffContainer,
248{
249 fn new<F>(
250 initial_values: Vector<VectorDiffContainerStreamElement<S>>,
251 inner_stream: S,
252 compare: F,
253 ) -> (Vector<VectorDiffContainerStreamElement<S>>, Self)
254 where
255 F: Fn(
256 &VectorDiffContainerStreamElement<S>,
257 &VectorDiffContainerStreamElement<S>,
258 ) -> Ordering,
259 {
260 let mut initial_values = initial_values.into_iter().enumerate().collect::<Vector<_>>();
261 initial_values.sort_by(|(_, left), (_, right)| compare(left, right));
262
263 (
264 initial_values.iter().map(|(_, value)| value.clone()).collect(),
265 Self {
266 inner_stream,
267 buffered_vector: initial_values,
268 ready_values: Default::default(),
269 },
270 )
271 }
272
273 fn poll_next<F>(
274 self: Pin<&mut Self>,
275 cx: &mut task::Context<'_>,
276 compare: F,
277 ) -> Poll<Option<S::Item>>
278 where
279 F: Fn(
280 &VectorDiffContainerStreamElement<S>,
281 &VectorDiffContainerStreamElement<S>,
282 ) -> Ordering
283 + Copy,
284 {
285 let mut this = self.project();
286
287 loop {
288 // First off, if any values are ready, return them.
289 if let Some(value) = S::Item::pop_from_sort_buf(this.ready_values) {
290 return Poll::Ready(Some(value));
291 }
292
293 // Poll `VectorDiff`s from the `inner_stream`.
294 let Some(diffs) = ready!(this.inner_stream.as_mut().poll_next(cx)) else {
295 return Poll::Ready(None);
296 };
297
298 // Consume and apply the diffs if possible.
299 let ready = diffs.push_into_sort_buf(this.ready_values, |diff| {
300 handle_diff_and_update_buffered_vector(diff, compare, this.buffered_vector)
301 });
302
303 if let Some(diff) = ready {
304 return Poll::Ready(Some(diff));
305 }
306
307 // Else loop and poll the streams again.
308 }
309 }
310}
311
312/// Map a `VectorDiff` to potentially `VectorDiff`s. Keep in mind that
313/// `buffered_vector` contains the sorted values.
314///
315/// When looking for the _position_ of a value (e.g. where to insert a new
316/// value?), `Vector::binary_search_by` is used — it is possible because the
317/// `Vector` is sorted. When looking for the _unsorted index_ of a value,
318/// `Iterator::position` is used.
319fn handle_diff_and_update_buffered_vector<T, F>(
320 diff: VectorDiff<T>,
321 compare: F,
322 buffered_vector: &mut Vector<(usize, T)>,
323) -> SmallVec<[VectorDiff<T>; 2]>
324where
325 T: Clone,
326 F: Fn(&T, &T) -> Ordering,
327{
328 let mut result = SmallVec::new();
329
330 match diff {
331 VectorDiff::Append { values: new_values } => {
332 // Sort `new_values`.
333 let mut new_values = {
334 // Calculate the `new_values` with their `unsorted_index`.
335 // The `unsorted_index` is the index of the new value in `new_values` + an
336 // offset, where the offset is given by `offset`, i.e the actual size of the
337 // `buffered_vector`.
338 let offset = buffered_vector.len();
339 let mut new_values = new_values
340 .into_iter()
341 .enumerate()
342 .map(|(unsorted_index, value)| (unsorted_index + offset, value))
343 .collect::<Vector<_>>();
344
345 // Now, we can sort `new_values`.
346 new_values.sort_by(|(_, left), (_, right)| compare(left, right));
347
348 new_values
349 };
350
351 // If `buffered_vector` is empty, all `new_values` are appended.
352 if buffered_vector.is_empty() {
353 buffered_vector.append(new_values.clone());
354 result.push(VectorDiff::Append {
355 values: new_values.into_iter().map(|(_, value)| value).collect(),
356 });
357 } else {
358 // Read the first item of `new_values`. We get a reference to it.
359 //
360 // Why using `Vector::get`? We _could_ use `new_values.pop_front()` to get
361 // ownership of `new_value`. But in the slow path, in the `_` branch, we
362 // would need to generate a `VectorDiff::PushBack`, followed by the
363 // `VectorDiff::Append` outside this loop, which is 2 diffs. Or, alternatively,
364 // we would need to `push_front` the `new_value` again, which has a cost too.
365 // By using a reference, and `pop_front`ing when necessary, we reduce the number
366 // of diffs.
367 while let Some((_, new_value)) = new_values.get(0) {
368 // Fast path.
369 //
370 // If `new_value`, i.e. the first item from `new_values`, is greater than or
371 // equal to the last item from `buffered_vector`, it means
372 // that all items in `new_values` can be appended. That's because `new_values`
373 // is already sorted.
374 if compare(
375 new_value,
376 buffered_vector
377 .last()
378 .map(|(_, value)| value)
379 .expect("`buffered_vector` cannot be empty"),
380 )
381 .is_ge()
382 {
383 // `new_value` isn't consumed. Let's break the loop and emit a
384 // `VectorDiff::Append` just hereinafter.
385 break;
386 }
387 // Slow path.
388 //
389 // Look for the position where to insert the `new_value`.
390 else {
391 // Find the position where to insert `new_value`.
392 match buffered_vector
393 .binary_search_by(|(_, value)| compare(value, new_value))
394 {
395 // Somewhere?
396 Ok(index) | Err(index) if index != buffered_vector.len() => {
397 // Insert the new value. We get it by using `pop_front` on
398 // `new_values`. This time the new value is consumed.
399 let (unsorted_index, new_value) =
400 new_values.pop_front().expect("`new_values` cannot be empty");
401
402 buffered_vector.insert(index, (unsorted_index, new_value.clone()));
403 result.push(
404 // At the beginning? Let's emit a `VectorDiff::PushFront`.
405 if index == 0 {
406 VectorDiff::PushFront { value: new_value }
407 }
408 // Somewhere in the middle? Let's emit a `VectorDiff::Insert`.
409 else {
410 VectorDiff::Insert { index, value: new_value }
411 },
412 );
413 }
414 // At the end?
415 _ => {
416 // `new_value` isn't consumed. Let's break the loop and emit a
417 // `VectorDiff::Append` just after.
418 break;
419 }
420 }
421 }
422 }
423
424 // Some values have not been inserted. Based on our algorithm, it means they
425 // must be appended.
426 if new_values.is_empty().not() {
427 buffered_vector.append(new_values.clone());
428 result.push(VectorDiff::Append {
429 values: new_values.into_iter().map(|(_, value)| value).collect(),
430 });
431 }
432 }
433 }
434 VectorDiff::Clear => {
435 // Nothing to do but clear.
436 buffered_vector.clear();
437 result.push(VectorDiff::Clear);
438 }
439 VectorDiff::PushFront { value: new_value } => {
440 // The unsorted index is inevitably 0, because we push a new item at the front
441 // of the vector.
442 let unsorted_index = 0;
443
444 // Shift all unsorted indices to the right.
445 buffered_vector.iter_mut().for_each(|(unsorted_index, _)| *unsorted_index += 1);
446
447 // Find where to insert the `new_value`.
448 match buffered_vector.binary_search_by(|(_, value)| compare(value, &new_value)) {
449 // At the beginning? Let's emit a `VectorDiff::PushFront`.
450 Ok(0) | Err(0) => {
451 buffered_vector.push_front((unsorted_index, new_value.clone()));
452 result.push(VectorDiff::PushFront { value: new_value });
453 }
454 // Somewhere in the middle? Let's emit a `VectorDiff::Insert`.
455 Ok(index) | Err(index) if index != buffered_vector.len() => {
456 buffered_vector.insert(index, (unsorted_index, new_value.clone()));
457 result.push(VectorDiff::Insert { index, value: new_value });
458 }
459 // At the end? Let's emit a `VectorDiff::PushBack`.
460 _ => {
461 buffered_vector.push_back((unsorted_index, new_value.clone()));
462 result.push(VectorDiff::PushBack { value: new_value });
463 }
464 }
465 }
466 VectorDiff::PushBack { value: new_value } => {
467 let buffered_vector_length = buffered_vector.len();
468
469 // The unsorted index is inevitably the size of `buffered_vector`, because
470 // we push a new item at the back of the vector.
471 let unsorted_index = buffered_vector_length;
472
473 // Find where to insert the `new_value`.
474 match buffered_vector.binary_search_by(|(_, value)| compare(value, &new_value)) {
475 // At the beginning? Let's emit a `VectorDiff::PushFront`.
476 Ok(0) | Err(0) => {
477 buffered_vector.push_front((unsorted_index, new_value.clone()));
478 result.push(VectorDiff::PushFront { value: new_value });
479 }
480 // Somewhere in the middle? Let's emit a `VectorDiff::Insert`.
481 Ok(index) | Err(index) if index != buffered_vector_length => {
482 buffered_vector.insert(index, (unsorted_index, new_value.clone()));
483 result.push(VectorDiff::Insert { index, value: new_value });
484 }
485 // At the end? Let's emit a `VectorDiff::PushBack`.
486 _ => {
487 buffered_vector.push_back((unsorted_index, new_value.clone()));
488 result.push(VectorDiff::PushBack { value: new_value });
489 }
490 }
491 }
492 VectorDiff::Insert { index: new_unsorted_index, value: new_value } => {
493 // Shift all unsorted indices after `new_unsorted_index` to the right.
494 buffered_vector.iter_mut().for_each(|(unsorted_index, _)| {
495 if *unsorted_index >= new_unsorted_index {
496 *unsorted_index += 1;
497 }
498 });
499
500 // Find where to insert the `new_value`.
501 match buffered_vector.binary_search_by(|(_, value)| compare(value, &new_value)) {
502 // At the beginning? Let's emit a `VectorDiff::PushFront`.
503 Ok(0) | Err(0) => {
504 buffered_vector.push_front((new_unsorted_index, new_value.clone()));
505 result.push(VectorDiff::PushFront { value: new_value });
506 }
507 // Somewhere in the middle? Let's emit a `VectorDiff::Insert`.
508 Ok(index) | Err(index) if index != buffered_vector.len() => {
509 buffered_vector.insert(index, (new_unsorted_index, new_value.clone()));
510 result.push(VectorDiff::Insert { index, value: new_value });
511 }
512 // At the end? Let's emit a `VectorDiff::PushBack`.
513 _ => {
514 buffered_vector.push_back((new_unsorted_index, new_value.clone()));
515 result.push(VectorDiff::PushBack { value: new_value });
516 }
517 }
518 }
519 VectorDiff::PopFront => {
520 let last_index = buffered_vector.len() - 1;
521
522 // Find the position and shift all unsorted indices to the left safely.
523 // Also, find the value to remove.
524 let position = buffered_vector
525 .iter_mut()
526 .enumerate()
527 .fold(None, |mut position, (index, (unsorted_index, _))| {
528 // Position has been found.
529 if position.is_none() && *unsorted_index == 0 {
530 position = Some(index);
531 }
532 // Otherwise, let's shift all other unsorted indices to the left.
533 // Value with an `unsorted_index` of 0 will be removed hereinafter.
534 else {
535 *unsorted_index -= 1;
536 }
537
538 position
539 })
540 .expect("`buffered_vector` must have an item with an unsorted index of 0");
541
542 match position {
543 // At the beginning? Let's emit a `VectorDiff::PopFront`.
544 0 => {
545 buffered_vector.pop_front();
546 result.push(VectorDiff::PopFront);
547 }
548 // At the end? Let's emit a `VectorDiff::PopBack`.
549 index if index == last_index => {
550 buffered_vector.pop_back();
551 result.push(VectorDiff::PopBack);
552 }
553 // Somewhere in the middle? Let's emit a `VectorDiff::Remove`.
554 index => {
555 buffered_vector.remove(index);
556 result.push(VectorDiff::Remove { index });
557 }
558 }
559 }
560 VectorDiff::PopBack => {
561 let last_index = buffered_vector.len() - 1;
562
563 // Find the value to remove.
564 match buffered_vector
565 .iter()
566 .position(|(unsorted_index, _)| *unsorted_index == last_index)
567 .expect(
568 "`buffered_vector` must have an item with an unsorted index of `last_index`",
569 ) {
570 // At the beginning? Let's emit a `VectorDiff::PopFront`.
571 0 => {
572 buffered_vector.pop_front();
573 result.push(VectorDiff::PopFront);
574 }
575 // At the end? Let's emit a `VectorDiff::PopBack`.
576 index if index == last_index => {
577 buffered_vector.pop_back();
578 result.push(VectorDiff::PopBack);
579 }
580 // Somewhere in the middle? Let's emit a `VectorDiff::Remove`.
581 index => {
582 buffered_vector.remove(index);
583 result.push(VectorDiff::Remove { index });
584 }
585 }
586 }
587 VectorDiff::Remove { index: new_unsorted_index } => {
588 let last_index = buffered_vector.len() - 1;
589
590 // Shift all items with an `unsorted_index` greater than `new_unsorted_index` to
591 // the left.
592 // Also, find the value to remove.
593 let position = buffered_vector
594 .iter_mut()
595 .enumerate()
596 .fold(None, |mut position, (index, (unsorted_index, _))| {
597 if position.is_none() && *unsorted_index == new_unsorted_index {
598 position = Some(index);
599 }
600
601 if *unsorted_index > new_unsorted_index {
602 *unsorted_index -= 1;
603 }
604
605 position
606 })
607 .expect("`buffered_vector` must contain an item with an unsorted index of `new_unsorted_index`");
608
609 match position {
610 // At the beginning? Let's emit a `VectorDiff::PopFront`.
611 0 => {
612 buffered_vector.pop_front();
613 result.push(VectorDiff::PopFront);
614 }
615 // At the end? Let's emit a `VectorDiff::PopBack`.
616 index if index == last_index => {
617 buffered_vector.pop_back();
618 result.push(VectorDiff::PopBack);
619 }
620 // Somewhere in the middle? Let's emit a `VectorDiff::Remove`.
621 index => {
622 buffered_vector.remove(index);
623 result.push(VectorDiff::Remove { index });
624 }
625 }
626 }
627 VectorDiff::Set { index: unsorted_index, value: new_value } => {
628 // A `Set` must be treated as a `Remove` + `Insert` with an optimisation to
629 // simplify the generated diffs.
630 // Note that the unsorted indexes don't need to be updated.
631
632 let last_index = buffered_vector.len() - 1;
633
634 // Find the `old_index`.
635 let old_index = buffered_vector
636 .iter()
637 .position(|(unsorted_index_candidate, _)| *unsorted_index_candidate == unsorted_index)
638 .expect("`buffered_vector` must contain an item with an unsorted index of `new_unsorted_index`");
639
640 // Remove the old value, so that `new_value` is not compared to the old value.
641 // This is necessary if the two values are shallow clones of each others.
642 buffered_vector.remove(old_index);
643 // `result` is updated later, in the next `match` block, to optimise the diffs.
644
645 let new_index =
646 match buffered_vector.binary_search_by(|(_, value)| compare(value, &new_value)) {
647 Ok(index) => index,
648 Err(index) => index,
649 };
650
651 // Insert the new value at the correct position.
652 buffered_vector.insert(new_index, (unsorted_index, new_value.clone()));
653
654 // We are removing and inserting at the same position. We can emit a
655 // `VectorDiff::Set` instead of one `VectorDiff::Remove` followed by a
656 // `VectorDiff::Insert`.
657 if old_index == new_index {
658 result.push(VectorDiff::Set { index: new_index, value: new_value });
659 } else {
660 result.push(VectorDiff::Remove { index: old_index });
661
662 match new_index {
663 // At the beginning? Let's emit a `VectorDiff::PopFront`.
664 0 => {
665 result.push(VectorDiff::PushFront { value: new_value });
666 }
667 // At the end? Let's emit a `VectorDiff::PopBack`.
668 index if index == last_index => {
669 result.push(VectorDiff::PushBack { value: new_value });
670 }
671 // Somewhere in the middle? Let's emit a `VectorDiff::Insert`.
672 index => {
673 result.push(VectorDiff::Insert { index, value: new_value });
674 }
675 }
676 }
677 }
678 VectorDiff::Truncate { length: new_length } => {
679 // Keep values where their `unsorted_index` is lower than the `new_length`.
680 buffered_vector.retain(|(unsorted_index, _)| *unsorted_index < new_length);
681 result.push(VectorDiff::Truncate { length: new_length });
682 }
683 VectorDiff::Reset { values: new_values } => {
684 // Calculate the `new_values` with their `unsorted_index`.
685 let mut new_values = new_values.into_iter().enumerate().collect::<Vector<_>>();
686
687 // Now, we can sort `new_values`.
688 new_values.sort_by(|(_, left), (_, right)| compare(left, right));
689
690 // Finally, update `buffered_vector` and create the `VectorDiff::Reset`.
691 *buffered_vector = new_values.clone();
692 result.push(VectorDiff::Reset {
693 values: new_values.into_iter().map(|(_, value)| value).collect(),
694 });
695 }
696 }
697
698 result
699}