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}