Skip to main content

morphix/impls/slices/
vec_deque.rs

1//! Observer implementation for [`VecDeque<T>`].
2
3use std::cell::UnsafeCell;
4use std::collections::vec_deque::Drain;
5use std::collections::{TryReserveError, VecDeque};
6use std::fmt::Debug;
7use std::marker::PhantomData;
8use std::ops::{Bound, Deref, DerefMut, Index, IndexMut, RangeBounds};
9
10use serde::Serialize;
11
12use crate::helper::macros::{default_impl_ref_observe, delegate_methods};
13use crate::helper::{AsDeref, AsDerefMut, ObserverState, Pointer, QuasiObserver, Succ, Unsigned, Zero};
14use crate::observe::{DefaultSpec, Observer, SerializeObserver};
15use crate::{MutationKind, Mutations, Observe, PathSegment};
16
17/// Observer state for [`VecDeque<T>`], tracking back-end
18/// [`Append`](MutationKind::Append) / [`Truncate`](MutationKind::Truncate) boundaries.
19///
20/// Front-end mutations (`push_front`, `pop_front`) trigger a full
21/// [`Replace`](MutationKind::Replace) because the current [`MutationKind`] set has no `Prepend`
22/// variant.
23struct VecDequeObserverState<O> {
24    /// Number of elements truncated from the back since the last flush.
25    back_truncate_len: usize,
26    /// Logical index dividing "existing" elements from "appended" elements at the back.
27    /// Elements at indices `[0, back_append_index)` are existing; `[back_append_index, len)` are
28    /// appended.
29    back_append_index: usize,
30    /// Whether a front-end mutation (push_front / pop_front) occurred, forcing full Replace.
31    front_mutated: bool,
32    /// Lazily-initialized element observer storage.
33    ///
34    /// Mirrors the logical layout of the observed `VecDeque<T>`. Observers are created lazily
35    /// via [`relocate`] on first mutable access.
36    inner: UnsafeCell<VecDeque<O>>,
37}
38
39impl<O> VecDequeObserverState<O> {
40    fn mark_back_truncate(&mut self, new_len: usize) {
41        self.back_truncate_len += self.back_append_index - new_len;
42        self.back_append_index = new_len;
43    }
44
45    /// Full invalidation: all existing content is lost, emit Replace on next flush.
46    /// Does NOT set front_mutated — that's only for explicit front-end operations.
47    fn mark_replace(&mut self) {
48        self.inner.get_mut().clear();
49        self.back_truncate_len += self.back_append_index;
50        self.back_append_index = 0;
51    }
52}
53
54impl<O> ObserverState for VecDequeObserverState<O>
55where
56    O: Observer<InnerDepth = Zero, Head: Sized>,
57{
58    type Target = VecDeque<O::Head>;
59
60    fn invalidate(this: &mut Self, _: &VecDeque<O::Head>) {
61        this.mark_replace();
62    }
63}
64
65/// Observer implementation for [`VecDeque<T>`].
66///
67/// Precisely tracks back-end `push_back` / `pop_back` as [`Append`](MutationKind::Append) /
68/// [`Truncate`](MutationKind::Truncate). Front-end mutations and arbitrary modifications
69/// fall back to [`Replace`](MutationKind::Replace).
70///
71/// Inner element observers are stored in a parallel `VecDeque<O>`, enabling fine-grained
72/// mutation tracking for individual elements (e.g., modifying a field of a struct inside the
73/// deque produces a path like `[-2].field` instead of a whole-deque Replace).
74pub struct VecDequeObserver<'ob, O, S: ?Sized, D = Zero> {
75    ptr: Pointer<S>,
76    state: VecDequeObserverState<O>,
77    phantom: PhantomData<&'ob mut D>,
78}
79
80impl<'ob, O, S: ?Sized, D> Deref for VecDequeObserver<'ob, O, S, D> {
81    type Target = Pointer<S>;
82
83    fn deref(&self) -> &Self::Target {
84        &self.ptr
85    }
86}
87
88impl<'ob, O, S: ?Sized, D> DerefMut for VecDequeObserver<'ob, O, S, D> {
89    fn deref_mut(&mut self) -> &mut Self::Target {
90        std::ptr::from_mut(self).expose_provenance();
91        Pointer::invalidate(&mut self.ptr);
92        &mut self.ptr
93    }
94}
95
96impl<'ob, O, S: ?Sized, D> QuasiObserver for VecDequeObserver<'ob, O, S, D>
97where
98    D: Unsigned,
99    O: Observer<InnerDepth = Zero, Head: Sized>,
100    S: AsDeref<D, Target = VecDeque<O::Head>>,
101{
102    type Head = S;
103    type OuterDepth = Succ<Zero>;
104    type InnerDepth = D;
105
106    fn invalidate(this: &mut Self) {
107        this.state.mark_replace();
108    }
109}
110
111impl<'ob, O, S: ?Sized, D> Observer for VecDequeObserver<'ob, O, S, D>
112where
113    D: Unsigned,
114    O: Observer<InnerDepth = Zero, Head: Sized>,
115    S: AsDerefMut<D, Target = VecDeque<O::Head>>,
116{
117    fn observe(head: &mut Self::Head) -> Self {
118        let len = head.as_deref_mut().len();
119        Self {
120            state: VecDequeObserverState {
121                back_truncate_len: 0,
122                back_append_index: len,
123                front_mutated: false,
124                inner: UnsafeCell::new(VecDeque::new()),
125            },
126            ptr: Pointer::new(head),
127            phantom: PhantomData,
128        }
129    }
130
131    unsafe fn relocate(this: &mut Self, head: &mut Self::Head) {
132        Pointer::set(this, head);
133    }
134}
135
136impl<'ob, O, S: ?Sized, D> SerializeObserver for VecDequeObserver<'ob, O, S, D>
137where
138    D: Unsigned,
139    O: Observer<InnerDepth = Zero, Head: Sized> + SerializeObserver,
140    O::Head: Serialize + 'static,
141    S: AsDerefMut<D, Target = VecDeque<O::Head>>,
142{
143    unsafe fn flush(this: &mut Self) -> Mutations {
144        let deque = (*this.ptr).as_deref_mut();
145        let len = deque.len();
146        let back_append_index = core::mem::replace(&mut this.state.back_append_index, len);
147        let back_truncate_len = core::mem::replace(&mut this.state.back_truncate_len, 0);
148        let front_mutated = core::mem::replace(&mut this.state.front_mutated, false);
149
150        // Make contiguous so we can take slices for serialization.
151        let slice = deque.make_contiguous();
152
153        // If front was mutated, or if all existing content was replaced, emit whole Replace.
154        if front_mutated || (back_append_index == 0 && back_truncate_len > 0) {
155            if len > 0 || back_truncate_len > 0 {
156                // Clear stale inner observers.
157                this.state.inner.get_mut().clear();
158                return Mutations::replace(slice);
159            }
160            return Mutations::new();
161        }
162
163        let mut mutations = Mutations::new();
164        #[cfg(feature = "truncate")]
165        if back_truncate_len > 0 {
166            mutations.extend(MutationKind::Truncate(back_truncate_len));
167        }
168
169        // Ensure inner observers exist for existing elements so we can flush them.
170        unsafe { relocate(&this.state.inner, &mut slice[..back_append_index]) };
171
172        #[cfg(feature = "append")]
173        if len > back_append_index {
174            mutations.extend(Mutations::append(&slice[back_append_index..]));
175        }
176
177        // Flush inner observers for existing elements.
178        let inner = this.state.inner.get_mut();
179        // inner might be shorter than back_append_index if not all elements were accessed;
180        // relocate above ensures it's at least back_append_index long.
181        let existing_len = back_append_index.min(inner.len());
182        let existing = inner.make_contiguous();
183        let mut is_replace = true;
184        for (index, ob) in existing[..existing_len].iter_mut().enumerate().rev() {
185            let mutations_i = unsafe { SerializeObserver::flush(ob) };
186            is_replace &= mutations_i.is_replace();
187            mutations.insert(PathSegment::Negative(len - index), mutations_i);
188        }
189
190        // Clear stale observers beyond the existing region.
191        inner.truncate(existing_len);
192
193        if is_replace && (back_append_index > 0 || back_truncate_len > 0) {
194            return Mutations::replace(slice);
195        }
196
197        mutations
198    }
199}
200
201/// Ensures element observers exist for all elements and updates their pointers.
202///
203/// Creates observers for any new elements via [`Observer::observe`] and calls
204/// [`Observer::relocate`] on existing observers to update their pointers.
205///
206/// # Safety
207///
208/// The caller must ensure no references from previous `relocate` calls are alive.
209unsafe fn relocate<O>(inner: &UnsafeCell<VecDeque<O>>, deque_slice: &mut [O::Head])
210where
211    O: Observer<InnerDepth = Zero, Head: Sized>,
212{
213    let observers = unsafe { &mut *inner.get() };
214    if observers.len() < deque_slice.len() {
215        for value in deque_slice[observers.len()..].iter_mut() {
216            observers.push_back(O::observe(value));
217        }
218    }
219    observers.truncate(deque_slice.len());
220    let ob_contiguous = observers.make_contiguous();
221    for (ob, value) in ob_contiguous.iter_mut().zip(deque_slice.iter_mut()) {
222        unsafe { Observer::relocate(ob, value) };
223    }
224}
225
226impl<'ob, O, S: ?Sized, D> VecDequeObserver<'ob, O, S, D>
227where
228    D: Unsigned,
229    O: Observer<InnerDepth = Zero, Head: Sized>,
230    S: AsDerefMut<D, Target = VecDeque<O::Head>>,
231{
232    delegate_methods! { untracked_mut() as VecDeque =>
233        pub fn reserve_exact(&mut self, additional: usize);
234        pub fn reserve(&mut self, additional: usize);
235        pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError>;
236        pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError>;
237        pub fn shrink_to_fit(&mut self);
238        pub fn shrink_to(&mut self, min_capacity: usize);
239    }
240
241    /// See [`VecDeque::make_contiguous`].
242    ///
243    /// This only rearranges internal memory layout without changing logical order.
244    /// Returns a mutable slice of inner element observers.
245    pub fn make_contiguous(&mut self) -> &mut [O] {
246        let deque = (*self.ptr).as_deref_mut();
247        let deque_slice = deque.make_contiguous();
248        unsafe { relocate(&self.state.inner, deque_slice) };
249        self.state.inner.get_mut().make_contiguous()
250    }
251
252    /// Ensures element observers exist and returns a mutable reference at `index`.
253    #[expect(clippy::mut_from_ref)]
254    fn force_index(&self, index: usize) -> Option<&mut O> {
255        let deque = unsafe { Pointer::as_mut(&self.ptr).as_deref_mut() };
256        let len = deque.len();
257        if index >= len {
258            return None;
259        }
260        // Make contiguous so relocate can work with a slice.
261        let slice = deque.make_contiguous();
262        unsafe { relocate(&self.state.inner, slice) };
263        let observers = unsafe { &mut *self.state.inner.get() };
264        observers.get_mut(index)
265    }
266
267    /// Ensures element observers exist and returns mutable references to all.
268    fn force_all(&mut self) -> &mut VecDeque<O> {
269        let deque = (*self.ptr).as_deref_mut();
270        let slice = deque.make_contiguous();
271        unsafe { relocate(&self.state.inner, slice) };
272        self.state.inner.get_mut()
273    }
274
275    /// See [`VecDeque::get_mut`].
276    pub fn get_mut(&mut self, index: usize) -> Option<&mut O> {
277        let deque = (*self.ptr).as_deref_mut();
278        let len = deque.len();
279        if index >= len {
280            return None;
281        }
282        let slice = deque.make_contiguous();
283        unsafe { relocate(&self.state.inner, slice) };
284        self.state.inner.get_mut().get_mut(index)
285    }
286
287    /// See [`VecDeque::front_mut`].
288    pub fn front_mut(&mut self) -> Option<&mut O> {
289        if (*self).untracked_ref().is_empty() {
290            return None;
291        }
292        self.get_mut(0)
293    }
294
295    /// See [`VecDeque::back_mut`].
296    pub fn back_mut(&mut self) -> Option<&mut O> {
297        let len = (*self).untracked_ref().len();
298        if len == 0 {
299            return None;
300        }
301        self.get_mut(len - 1)
302    }
303
304    /// See [`VecDeque::iter_mut`].
305    ///
306    /// Returns an iterator over mutable references to inner element observers.
307    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut O> {
308        let observers = self.force_all();
309        observers.iter_mut()
310    }
311
312    /// See [`VecDeque::as_mut_slices`].
313    ///
314    /// Returns observer slices. Since `force_all` makes the observer deque contiguous,
315    /// the second slice will be empty.
316    pub fn as_mut_slices(&mut self) -> (&mut [O], &mut [O]) {
317        self.force_all();
318        self.state.inner.get_mut().as_mut_slices()
319    }
320
321    /// See [`VecDeque::range_mut`].
322    pub fn range_mut<R>(&mut self, range: R) -> impl Iterator<Item = &mut O>
323    where
324        R: RangeBounds<usize> + Clone,
325    {
326        let deque = (*self.ptr).as_deref_mut();
327        let slice = deque.make_contiguous();
328        unsafe { relocate(&self.state.inner, slice) };
329        self.state.inner.get_mut().range_mut(range)
330    }
331
332    /// See [`VecDeque::swap`].
333    pub fn swap(&mut self, i: usize, j: usize) {
334        if i != j {
335            // Invalidate observers for swapped elements.
336            let observers = self.state.inner.get_mut();
337            if let Some(ob) = observers.get_mut(i) {
338                QuasiObserver::invalidate(ob);
339            }
340            if let Some(ob) = observers.get_mut(j) {
341                QuasiObserver::invalidate(ob);
342            }
343            self.untracked_mut().swap(i, j);
344        }
345    }
346
347    /// See [`VecDeque::rotate_left`].
348    pub fn rotate_left(&mut self, n: usize) {
349        if n != 0 && (*self).untracked_ref().len() > 1 {
350            self.tracked_mut().rotate_left(n);
351        }
352    }
353
354    /// See [`VecDeque::rotate_right`].
355    pub fn rotate_right(&mut self, n: usize) {
356        if n != 0 && (*self).untracked_ref().len() > 1 {
357            self.tracked_mut().rotate_right(n);
358        }
359    }
360
361    /// See [`VecDeque::push_front`].
362    pub fn push_front(&mut self, value: O::Head) {
363        self.state.front_mutated = true;
364        self.state.inner.get_mut().clear();
365        self.untracked_mut().push_front(value);
366    }
367
368    /// See [`VecDeque::pop_front`].
369    pub fn pop_front(&mut self) -> Option<O::Head> {
370        let value = self.untracked_mut().pop_front()?;
371        self.state.front_mutated = true;
372        self.state.inner.get_mut().clear();
373        Some(value)
374    }
375
376    /// See [`VecDeque::pop_front_if`].
377    pub fn pop_front_if(&mut self, predicate: impl FnOnce(&mut O::Head) -> bool) -> Option<O::Head> {
378        // We need to check predicate without committing to front_mutated.
379        let front = self.untracked_mut().front_mut()?;
380        if predicate(front) { self.pop_front() } else { None }
381    }
382
383    /// See [`VecDeque::swap_remove_front`].
384    pub fn swap_remove_front(&mut self, index: usize) -> Option<O::Head> {
385        let value = self.untracked_mut().swap_remove_front(index)?;
386        self.state.front_mutated = true;
387        self.state.inner.get_mut().clear();
388        Some(value)
389    }
390}
391
392#[cfg(feature = "append")]
393impl<'ob, O, S: ?Sized, D> VecDequeObserver<'ob, O, S, D>
394where
395    D: Unsigned,
396    O: Observer<InnerDepth = Zero, Head: Sized>,
397    S: AsDerefMut<D, Target = VecDeque<O::Head>>,
398{
399    /// See [`VecDeque::push_back`].
400    pub fn push_back(&mut self, value: O::Head) {
401        self.untracked_mut().push_back(value);
402    }
403
404    /// See [`VecDeque::append`].
405    pub fn append(&mut self, other: &mut VecDeque<O::Head>) {
406        self.untracked_mut().append(other);
407    }
408
409    /// See [`VecDeque::insert`].
410    pub fn insert(&mut self, index: usize, value: O::Head) {
411        if index >= self.state.back_append_index {
412            self.untracked_mut().insert(index, value);
413        } else {
414            self.state.inner.get_mut().clear();
415            self.tracked_mut().insert(index, value);
416        }
417    }
418}
419
420#[cfg(any(feature = "append", feature = "truncate"))]
421impl<'ob, O, S: ?Sized, D> VecDequeObserver<'ob, O, S, D>
422where
423    D: Unsigned,
424    O: Observer<InnerDepth = Zero, Head: Sized>,
425    S: AsDerefMut<D, Target = VecDeque<O::Head>>,
426{
427    /// See [`VecDeque::pop_back`].
428    pub fn pop_back(&mut self) -> Option<O::Head> {
429        let value = self.untracked_mut().pop_back()?;
430        let len = (*self).untracked_ref().len();
431        if len >= self.state.back_append_index {
432            // popped from appended region, no-op
433        } else if cfg!(feature = "truncate") && len + 1 == self.state.back_append_index {
434            self.state.mark_back_truncate(len);
435        } else {
436            self.state.mark_replace();
437        }
438        Some(value)
439    }
440
441    /// See [`VecDeque::pop_back_if`].
442    pub fn pop_back_if(&mut self, predicate: impl FnOnce(&mut O::Head) -> bool) -> Option<O::Head> {
443        let back = self.untracked_mut().back_mut()?;
444        if predicate(back) { self.pop_back() } else { None }
445    }
446
447    /// See [`VecDeque::clear`].
448    pub fn clear(&mut self) {
449        if self.state.back_append_index == 0 && !self.state.front_mutated {
450            self.untracked_mut().clear();
451        } else {
452            self.state.inner.get_mut().clear();
453            self.tracked_mut().clear();
454        }
455    }
456
457    /// See [`VecDeque::truncate`].
458    pub fn truncate(&mut self, len: usize) {
459        let bai = self.state.back_append_index;
460        if len >= bai {
461            self.untracked_mut().truncate(len);
462            return;
463        }
464        if cfg!(not(feature = "truncate")) || len == 0 {
465            self.state.inner.get_mut().clear();
466            self.tracked_mut().truncate(len);
467            return;
468        }
469        self.state.mark_back_truncate(len);
470        self.untracked_mut().truncate(len);
471    }
472
473    /// See [`VecDeque::remove`].
474    pub fn remove(&mut self, index: usize) -> Option<O::Head> {
475        let bai = self.state.back_append_index;
476        let value = self.untracked_mut().remove(index)?;
477        if index >= bai {
478            // removed from appended region, no-op
479        } else if cfg!(feature = "truncate") && index + 1 == bai {
480            self.state.mark_back_truncate(index);
481        } else {
482            self.state.mark_replace();
483        }
484        Some(value)
485    }
486
487    /// See [`VecDeque::swap_remove_back`].
488    pub fn swap_remove_back(&mut self, index: usize) -> Option<O::Head> {
489        let bai = self.state.back_append_index;
490        let value = self.untracked_mut().swap_remove_back(index)?;
491        if index >= bai {
492            // removed from appended region
493        } else if cfg!(feature = "truncate") && index + 1 == bai {
494            self.state.mark_back_truncate(index);
495        } else {
496            self.state.mark_replace();
497        }
498        Some(value)
499    }
500
501    /// See [`VecDeque::split_off`].
502    pub fn split_off(&mut self, at: usize) -> VecDeque<O::Head> {
503        let bai = self.state.back_append_index;
504        let split = self.untracked_mut().split_off(at);
505        if at >= bai {
506            // split from appended region, no-op
507        } else if cfg!(feature = "truncate") && at > 0 {
508            self.state.mark_back_truncate(at);
509        } else {
510            self.state.mark_replace();
511        }
512        split
513    }
514
515    /// See [`VecDeque::retain`].
516    pub fn retain<F>(&mut self, f: F)
517    where
518        F: FnMut(&O::Head) -> bool,
519    {
520        self.state.inner.get_mut().clear();
521        self.tracked_mut().retain(f);
522    }
523
524    /// See [`VecDeque::retain_mut`].
525    pub fn retain_mut<F>(&mut self, f: F)
526    where
527        F: FnMut(&mut O::Head) -> bool,
528    {
529        self.state.inner.get_mut().clear();
530        self.tracked_mut().retain_mut(f);
531    }
532
533    /// See [`VecDeque::resize_with`].
534    pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut() -> O::Head) {
535        let bai = self.state.back_append_index;
536        self.untracked_mut().resize_with(new_len, generator);
537        if new_len >= bai {
538            // grew or stayed same, no-op
539        } else if cfg!(feature = "truncate") && new_len > 0 {
540            self.state.mark_back_truncate(new_len);
541        } else {
542            self.state.mark_replace();
543        }
544    }
545
546    /// See [`VecDeque::drain`].
547    pub fn drain<R>(&mut self, range: R) -> Drain<'_, O::Head>
548    where
549        R: RangeBounds<usize>,
550    {
551        let bai = self.state.back_append_index;
552        let start = match range.start_bound() {
553            Bound::Included(&n) => n,
554            Bound::Excluded(&n) => n + 1,
555            Bound::Unbounded => 0,
556        };
557        if start >= bai {
558            return self.untracked_mut().drain(range);
559        }
560        if cfg!(not(feature = "truncate")) || start == 0 {
561            self.state.inner.get_mut().clear();
562            return self.tracked_mut().drain(range);
563        }
564        let end = match range.end_bound() {
565            Bound::Included(&n) => n + 1,
566            Bound::Excluded(&n) => n,
567            Bound::Unbounded => (*self).untracked_ref().len(),
568        };
569        if end < bai {
570            self.state.inner.get_mut().clear();
571            return self.tracked_mut().drain(range);
572        }
573        self.state.mark_back_truncate(start);
574        self.state.inner.get_mut().clear();
575        self.tracked_mut().drain(range)
576    }
577}
578
579#[cfg(any(feature = "append", feature = "truncate"))]
580impl<'ob, O, S: ?Sized, D> VecDequeObserver<'ob, O, S, D>
581where
582    D: Unsigned,
583    O: Observer<InnerDepth = Zero, Head: Sized>,
584    O::Head: Clone,
585    S: AsDerefMut<D, Target = VecDeque<O::Head>>,
586{
587    /// See [`VecDeque::resize`].
588    pub fn resize(&mut self, new_len: usize, value: O::Head) {
589        let bai = self.state.back_append_index;
590        self.untracked_mut().resize(new_len, value);
591        if new_len >= bai {
592            // grew or stayed same
593        } else if cfg!(feature = "truncate") && new_len > 0 {
594            self.state.mark_back_truncate(new_len);
595        } else {
596            self.state.mark_replace();
597        }
598    }
599}
600
601#[cfg(feature = "append")]
602impl<'ob, O, S: ?Sized, D, U> Extend<U> for VecDequeObserver<'ob, O, S, D>
603where
604    D: Unsigned,
605    O: Observer<InnerDepth = Zero, Head: Sized>,
606    S: AsDerefMut<D, Target = VecDeque<O::Head>>,
607    VecDeque<O::Head>: Extend<U>,
608{
609    fn extend<I: IntoIterator<Item = U>>(&mut self, other: I) {
610        self.untracked_mut().extend(other);
611    }
612}
613
614impl<'ob, O, S: ?Sized, D> Index<usize> for VecDequeObserver<'ob, O, S, D>
615where
616    D: Unsigned,
617    O: Observer<InnerDepth = Zero, Head: Sized>,
618    S: AsDerefMut<D, Target = VecDeque<O::Head>>,
619{
620    type Output = O;
621
622    fn index(&self, index: usize) -> &Self::Output {
623        self.force_index(index).expect("index out of bounds")
624    }
625}
626
627impl<'ob, O, S: ?Sized, D> IndexMut<usize> for VecDequeObserver<'ob, O, S, D>
628where
629    D: Unsigned,
630    O: Observer<InnerDepth = Zero, Head: Sized>,
631    S: AsDerefMut<D, Target = VecDeque<O::Head>>,
632{
633    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
634        self.get_mut(index).expect("index out of bounds")
635    }
636}
637
638impl<'ob, O, S: ?Sized, D> Debug for VecDequeObserver<'ob, O, S, D>
639where
640    D: Unsigned,
641    O: Observer<InnerDepth = Zero, Head: Sized>,
642    O::Head: Debug,
643    S: AsDeref<D, Target = VecDeque<O::Head>>,
644{
645    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
646        f.debug_tuple("VecDequeObserver").field(&self.untracked_ref()).finish()
647    }
648}
649
650impl<'ob, O, S: ?Sized, D, U> PartialEq<VecDeque<U>> for VecDequeObserver<'ob, O, S, D>
651where
652    D: Unsigned,
653    O: Observer<InnerDepth = Zero, Head: Sized>,
654    S: AsDeref<D, Target = VecDeque<O::Head>>,
655    VecDeque<O::Head>: PartialEq<VecDeque<U>>,
656{
657    fn eq(&self, other: &VecDeque<U>) -> bool {
658        self.untracked_ref().eq(other)
659    }
660}
661
662impl<'ob, O1, O2, S1: ?Sized, S2: ?Sized, D1, D2> PartialEq<VecDequeObserver<'ob, O2, S2, D2>>
663    for VecDequeObserver<'ob, O1, S1, D1>
664where
665    D1: Unsigned,
666    D2: Unsigned,
667    O1: Observer<InnerDepth = Zero, Head: Sized>,
668    O2: Observer<InnerDepth = Zero, Head: Sized>,
669    S1: AsDeref<D1, Target = VecDeque<O1::Head>>,
670    S2: AsDeref<D2, Target = VecDeque<O2::Head>>,
671    VecDeque<O1::Head>: PartialEq<VecDeque<O2::Head>>,
672{
673    fn eq(&self, other: &VecDequeObserver<'ob, O2, S2, D2>) -> bool {
674        self.untracked_ref().eq(other.untracked_ref())
675    }
676}
677
678impl<'ob, O, S: ?Sized, D> Eq for VecDequeObserver<'ob, O, S, D>
679where
680    D: Unsigned,
681    O: Observer<InnerDepth = Zero, Head: Sized>,
682    O::Head: Eq,
683    S: AsDeref<D, Target = VecDeque<O::Head>>,
684{
685}
686
687impl<T: Observe> Observe for VecDeque<T> {
688    type Observer<'ob, S, D>
689        = VecDequeObserver<'ob, T::Observer<'ob, T, Zero>, S, D>
690    where
691        Self: 'ob,
692        D: Unsigned,
693        S: AsDerefMut<D, Target = Self> + ?Sized + 'ob;
694
695    type Spec = DefaultSpec;
696}
697
698default_impl_ref_observe! {
699    impl [T: Observe] RefObserve for VecDeque<T>;
700}
701
702#[cfg(test)]
703mod tests {
704    use std::collections::VecDeque;
705
706    use morphix_test_utils::*;
707    use serde_json::json;
708
709    use crate::adapter::Json;
710    use crate::observe::{ObserveExt, SerializeObserverExt};
711
712    #[test]
713    fn no_change_returns_none() {
714        let mut deque = VecDeque::from([1, 2, 3]);
715        let mut ob = deque.__observe();
716        let Json(mutation) = ob.flush().unwrap();
717        assert_eq!(mutation, None);
718    }
719
720    #[test]
721    fn reserve_returns_none() {
722        let mut deque = VecDeque::from([1, 2, 3]);
723        let mut ob = deque.__observe();
724        ob.reserve(100);
725        ob.shrink_to_fit();
726        let Json(mutation) = ob.flush().unwrap();
727        assert_eq!(mutation, None);
728    }
729
730    #[test]
731    fn make_contiguous_returns_none() {
732        let mut deque = VecDeque::new();
733        deque.push_back(1);
734        deque.push_back(2);
735        deque.push_front(0);
736        let mut ob = deque.__observe();
737        ob.make_contiguous();
738        let Json(mutation) = ob.flush().unwrap();
739        assert_eq!(mutation, None);
740    }
741
742    #[test]
743    fn push_back_triggers_append() {
744        let mut deque = VecDeque::from([1]);
745        let mut ob = deque.__observe();
746        ob.push_back(2);
747        ob.push_back(3);
748        let Json(mutation) = ob.flush().unwrap();
749        assert_eq!(mutation, Some(append!(_, json!([2, 3]))));
750    }
751
752    #[test]
753    fn extend_triggers_append() {
754        let mut deque = VecDeque::from([1]);
755        let mut ob = deque.__observe();
756        ob.extend([2, 3]);
757        let Json(mutation) = ob.flush().unwrap();
758        assert_eq!(mutation, Some(append!(_, json!([2, 3]))));
759    }
760
761    #[test]
762    fn append_other_deque() {
763        let mut deque = VecDeque::from([1]);
764        let mut ob = deque.__observe();
765        let mut other = VecDeque::from([4, 5]);
766        ob.append(&mut other);
767        let Json(mutation) = ob.flush().unwrap();
768        assert_eq!(mutation, Some(append!(_, json!([4, 5]))));
769    }
770
771    #[test]
772    fn pop_back_triggers_truncate() {
773        let mut deque = VecDeque::from([1, 2, 3]);
774        let mut ob = deque.__observe();
775        ob.pop_back();
776        ob.pop_back();
777        let Json(mutation) = ob.flush().unwrap();
778        assert_eq!(mutation, Some(truncate!(_, 2)));
779    }
780
781    #[test]
782    fn truncate_method() {
783        let mut deque = VecDeque::from([1, 2, 3, 4, 5]);
784        let mut ob = deque.__observe();
785        ob.truncate(2);
786        let Json(mutation) = ob.flush().unwrap();
787        assert_eq!(mutation, Some(truncate!(_, 3)));
788    }
789
790    #[test]
791    fn pop_back_then_push_back() {
792        let mut deque = VecDeque::from([1, 2, 3]);
793        let mut ob = deque.__observe();
794        ob.pop_back();
795        ob.push_back(4);
796        let Json(mutation) = ob.flush().unwrap();
797        assert_eq!(mutation, Some(batch!(_, truncate!(_, 1), append!(_, json!([4])))));
798    }
799
800    #[test]
801    fn pop_back_from_appended_region() {
802        let mut deque = VecDeque::from([1]);
803        let mut ob = deque.__observe();
804        ob.push_back(2);
805        ob.push_back(3);
806        ob.pop_back(); // popping from appended region
807        let Json(mutation) = ob.flush().unwrap();
808        assert_eq!(mutation, Some(append!(_, json!([2]))));
809    }
810
811    #[test]
812    fn push_front_triggers_replace() {
813        let mut deque = VecDeque::from([1, 2]);
814        let mut ob = deque.__observe();
815        ob.push_front(0);
816        let Json(mutation) = ob.flush().unwrap();
817        assert_eq!(mutation, Some(replace!(_, json!([0, 1, 2]))));
818    }
819
820    #[test]
821    fn pop_front_triggers_replace() {
822        let mut deque = VecDeque::from([1, 2, 3]);
823        let mut ob = deque.__observe();
824        ob.pop_front();
825        let Json(mutation) = ob.flush().unwrap();
826        assert_eq!(mutation, Some(replace!(_, json!([2, 3]))));
827    }
828
829    #[test]
830    fn pop_front_if_true_triggers_replace() {
831        let mut deque = VecDeque::from([1, 2, 3]);
832        let mut ob = deque.__observe();
833        let result = ob.pop_front_if(|x| *x == 1);
834        assert_eq!(result, Some(1));
835        let Json(mutation) = ob.flush().unwrap();
836        assert_eq!(mutation, Some(replace!(_, json!([2, 3]))));
837    }
838
839    #[test]
840    fn pop_front_if_false_returns_none() {
841        let mut deque = VecDeque::from([1, 2, 3]);
842        let mut ob = deque.__observe();
843        let result = ob.pop_front_if(|x| *x == 99);
844        assert_eq!(result, None);
845        let Json(mutation) = ob.flush().unwrap();
846        assert_eq!(mutation, None);
847    }
848
849    #[test]
850    fn push_front_overrides_back_append() {
851        let mut deque = VecDeque::from([1]);
852        let mut ob = deque.__observe();
853        ob.push_back(2);
854        ob.push_front(0); // front mutation overrides back tracking
855        let Json(mutation) = ob.flush().unwrap();
856        assert_eq!(mutation, Some(replace!(_, json!([0, 1, 2]))));
857    }
858
859    #[test]
860    fn deref_mut_triggers_replace() {
861        let mut deque = VecDeque::from([1, 2]);
862        let mut ob = deque.__observe();
863        ob.retain(|x| *x > 1);
864        let Json(mutation) = ob.flush().unwrap();
865        assert_eq!(mutation, Some(replace!(_, json!([2]))));
866    }
867
868    #[test]
869    fn empty_deque_no_mutation() {
870        let mut deque: VecDeque<i32> = VecDeque::new();
871        let mut ob = deque.__observe();
872        let Json(mutation) = ob.flush().unwrap();
873        assert_eq!(mutation, None);
874    }
875
876    #[test]
877    fn empty_deque_push_back() {
878        let mut deque: VecDeque<i32> = VecDeque::new();
879        let mut ob = deque.__observe();
880        ob.push_back(1);
881        let Json(mutation) = ob.flush().unwrap();
882        assert_eq!(mutation, Some(append!(_, json!([1]))));
883    }
884
885    #[test]
886    fn empty_deque_push_front() {
887        let mut deque: VecDeque<i32> = VecDeque::new();
888        let mut ob = deque.__observe();
889        ob.push_front(1);
890        let Json(mutation) = ob.flush().unwrap();
891        assert_eq!(mutation, Some(replace!(_, json!([1]))));
892    }
893
894    #[test]
895    fn clear_empty_deque() {
896        let mut deque: VecDeque<i32> = VecDeque::new();
897        let mut ob = deque.__observe();
898        ob.clear();
899        let Json(mutation) = ob.flush().unwrap();
900        assert_eq!(mutation, None);
901    }
902
903    #[test]
904    fn clear_nonempty_deque() {
905        let mut deque = VecDeque::from([1, 2, 3]);
906        let mut ob = deque.__observe();
907        ob.clear();
908        let Json(mutation) = ob.flush().unwrap();
909        assert_eq!(mutation, Some(replace!(_, json!([]))));
910    }
911
912    #[test]
913    fn split_off_from_existing() {
914        let mut deque = VecDeque::from([1, 2, 3, 4]);
915        let mut ob = deque.__observe();
916        let split = ob.split_off(2);
917        assert_eq!(split, VecDeque::from([3, 4]));
918        let Json(mutation) = ob.flush().unwrap();
919        assert_eq!(mutation, Some(truncate!(_, 2)));
920    }
921
922    #[test]
923    fn split_off_from_appended() {
924        let mut deque = VecDeque::from([1]);
925        let mut ob = deque.__observe();
926        ob.push_back(2);
927        ob.push_back(3);
928        let split = ob.split_off(2);
929        assert_eq!(split, VecDeque::from([3]));
930        let Json(mutation) = ob.flush().unwrap();
931        assert_eq!(mutation, Some(append!(_, json!([2]))));
932    }
933
934    #[test]
935    fn remove_at_back_append_boundary() {
936        let mut deque = VecDeque::from([1, 2, 3]);
937        let mut ob = deque.__observe();
938        let val = ob.remove(2);
939        assert_eq!(val, Some(3));
940        let Json(mutation) = ob.flush().unwrap();
941        assert_eq!(mutation, Some(truncate!(_, 1)));
942    }
943
944    #[test]
945    fn remove_from_middle_triggers_replace() {
946        let mut deque = VecDeque::from([1, 2, 3, 4]);
947        let mut ob = deque.__observe();
948        let val = ob.remove(1);
949        assert_eq!(val, Some(2));
950        let Json(mutation) = ob.flush().unwrap();
951        assert_eq!(mutation, Some(replace!(_, json!([1, 3, 4]))));
952    }
953
954    #[test]
955    fn insert_in_appended_region() {
956        let mut deque = VecDeque::from([1]);
957        let mut ob = deque.__observe();
958        ob.push_back(2);
959        ob.insert(2, 3); // insert at index 2, which is in appended region
960        let Json(mutation) = ob.flush().unwrap();
961        assert_eq!(mutation, Some(append!(_, json!([2, 3]))));
962    }
963
964    #[test]
965    fn insert_in_existing_region() {
966        let mut deque = VecDeque::from([1, 2, 3]);
967        let mut ob = deque.__observe();
968        ob.insert(1, 99);
969        let Json(mutation) = ob.flush().unwrap();
970        assert_eq!(mutation, Some(replace!(_, json!([1, 99, 2, 3]))));
971    }
972
973    #[test]
974    fn swap_remove_front_triggers_replace() {
975        let mut deque = VecDeque::from([1, 2, 3]);
976        let mut ob = deque.__observe();
977        let val = ob.swap_remove_front(1);
978        assert_eq!(val, Some(2));
979        let Json(mutation) = ob.flush().unwrap();
980        assert_eq!(mutation, Some(replace!(_, json!([1, 3]))));
981    }
982
983    #[test]
984    fn multiple_flushes() {
985        let mut deque = VecDeque::from([1, 2]);
986        let mut ob = deque.__observe();
987        ob.push_back(3);
988        let Json(m1) = ob.flush().unwrap();
989        assert_eq!(m1, Some(append!(_, json!([3]))));
990        // Second flush with no changes
991        let Json(m2) = ob.flush().unwrap();
992        assert_eq!(m2, None);
993        // Third flush with more changes
994        ob.pop_back();
995        let Json(m3) = ob.flush().unwrap();
996        assert_eq!(m3, Some(truncate!(_, 1)));
997    }
998
999    #[test]
1000    fn resize_shrink() {
1001        let mut deque = VecDeque::from([1, 2, 3, 4, 5]);
1002        let mut ob = deque.__observe();
1003        ob.resize(2, 0);
1004        let Json(mutation) = ob.flush().unwrap();
1005        assert_eq!(mutation, Some(truncate!(_, 3)));
1006    }
1007
1008    #[test]
1009    fn resize_grow() {
1010        let mut deque = VecDeque::from([1]);
1011        let mut ob = deque.__observe();
1012        ob.resize(3, 0);
1013        let Json(mutation) = ob.flush().unwrap();
1014        assert_eq!(mutation, Some(append!(_, json!([0, 0]))));
1015    }
1016
1017    #[test]
1018    fn pop_back_if_true() {
1019        let mut deque = VecDeque::from([1, 2, 3]);
1020        let mut ob = deque.__observe();
1021        let result = ob.pop_back_if(|x| *x == 3);
1022        assert_eq!(result, Some(3));
1023        let Json(mutation) = ob.flush().unwrap();
1024        assert_eq!(mutation, Some(truncate!(_, 1)));
1025    }
1026
1027    #[test]
1028    fn pop_back_if_false() {
1029        let mut deque = VecDeque::from([1, 2, 3]);
1030        let mut ob = deque.__observe();
1031        let result = ob.pop_back_if(|x| *x == 99);
1032        assert_eq!(result, None);
1033        let Json(mutation) = ob.flush().unwrap();
1034        assert_eq!(mutation, None);
1035    }
1036
1037    #[test]
1038    fn drain_from_appended() {
1039        let mut deque = VecDeque::from([1]);
1040        let mut ob = deque.__observe();
1041        ob.push_back(2);
1042        ob.push_back(3);
1043        let drained: Vec<_> = ob.drain(1..).collect();
1044        assert_eq!(drained, vec![2, 3]);
1045        let Json(mutation) = ob.flush().unwrap();
1046        assert_eq!(mutation, None); // drained only appended elements
1047    }
1048
1049    #[test]
1050    fn drain_straddles_boundary() {
1051        let mut deque = VecDeque::from([1, 2, 3]);
1052        let mut ob = deque.__observe();
1053        ob.push_back(4);
1054        let drained: Vec<_> = ob.drain(1..).collect();
1055        assert_eq!(drained, vec![2, 3, 4]);
1056        let Json(mutation) = ob.flush().unwrap();
1057        // Drain straddles the append boundary, so granular tracking is lost → Replace.
1058        assert_eq!(mutation, Some(replace!(_, json!([1]))));
1059    }
1060
1061    #[test]
1062    fn index_mut_triggers_replace() {
1063        let mut deque = VecDeque::from([1i32, 2, 3]);
1064        let mut ob = deque.__observe();
1065        **ob[1] = 99;
1066        let Json(mutation) = ob.flush().unwrap();
1067        assert_eq!(mutation, Some(replace!(-2, json!(99))));
1068    }
1069
1070    #[test]
1071    fn index_returns_inner_observer() {
1072        let mut deque = VecDeque::from(["hello".to_string(), "world".to_string()]);
1073        let mut ob = deque.__observe();
1074        // Access through index should return an observer, not raw T.
1075        assert_eq!(ob[0], "hello");
1076        assert_eq!(ob[1], "world");
1077        let Json(mutation) = ob.flush().unwrap();
1078        assert_eq!(mutation, None);
1079    }
1080
1081    #[test]
1082    fn modify_element_via_inner_observer() {
1083        let mut deque = VecDeque::from(["hello".to_string(), "world".to_string()]);
1084        let mut ob = deque.__observe();
1085        // Modify element through observer — should produce fine-grained mutation.
1086        // String's push_str produces Append at the element level.
1087        ob[0].push_str("!");
1088        let Json(mutation) = ob.flush().unwrap();
1089        assert_eq!(mutation, Some(append!(-2, json!("!"))));
1090    }
1091
1092    #[test]
1093    fn modify_multiple_elements_via_inner_observer() {
1094        let mut deque = VecDeque::from(["a".to_string(), "b".to_string(), "c".to_string()]);
1095        let mut ob = deque.__observe();
1096        ob[0].push_str("1");
1097        ob[2].push_str("3");
1098        let Json(mutation) = ob.flush().unwrap();
1099        assert_eq!(
1100            mutation,
1101            Some(batch!(_, append!(-1, json!("3")), append!(-3, json!("1"))))
1102        );
1103    }
1104
1105    #[test]
1106    fn get_mut_returns_observer() {
1107        let mut deque = VecDeque::from(["foo".to_string(), "bar".to_string()]);
1108        let mut ob = deque.__observe();
1109        let elem = ob.get_mut(1).unwrap();
1110        elem.push_str("baz");
1111        let Json(mutation) = ob.flush().unwrap();
1112        assert_eq!(mutation, Some(append!(-1, json!("baz"))));
1113    }
1114
1115    #[test]
1116    fn front_mut_returns_observer() {
1117        let mut deque = VecDeque::from(["first".to_string(), "second".to_string()]);
1118        let mut ob = deque.__observe();
1119        let front = ob.front_mut().unwrap();
1120        front.push_str("!");
1121        let Json(mutation) = ob.flush().unwrap();
1122        assert_eq!(mutation, Some(append!(-2, json!("!"))));
1123    }
1124
1125    #[test]
1126    fn back_mut_returns_observer() {
1127        let mut deque = VecDeque::from(["first".to_string(), "second".to_string()]);
1128        let mut ob = deque.__observe();
1129        let back = ob.back_mut().unwrap();
1130        back.push_str("!");
1131        let Json(mutation) = ob.flush().unwrap();
1132        assert_eq!(mutation, Some(append!(-1, json!("!"))));
1133    }
1134
1135    #[test]
1136    fn iter_mut_returns_observers() {
1137        let mut deque = VecDeque::from(["a".to_string(), "b".to_string(), "c".to_string()]);
1138        let mut ob = deque.__observe();
1139        for elem in ob.iter_mut() {
1140            elem.push_str("!");
1141        }
1142        let Json(mutation) = ob.flush().unwrap();
1143        // All elements have fine-grained Append mutations.
1144        // Since not all report Replace, they are emitted individually.
1145        assert_eq!(
1146            mutation,
1147            Some(batch!(
1148                _,
1149                append!(-1, json!("!")),
1150                append!(-2, json!("!")),
1151                append!(-3, json!("!"))
1152            ))
1153        );
1154    }
1155
1156    #[test]
1157    fn make_contiguous_returns_observer_slice() {
1158        let mut deque = VecDeque::from(["x".to_string(), "y".to_string()]);
1159        let mut ob = deque.__observe();
1160        let slice = ob.make_contiguous();
1161        slice[0].push_str("1");
1162        let Json(mutation) = ob.flush().unwrap();
1163        assert_eq!(mutation, Some(append!(-2, json!("1"))));
1164    }
1165
1166    #[test]
1167    fn modify_then_append() {
1168        let mut deque = VecDeque::from(["a".to_string()]);
1169        let mut ob = deque.__observe();
1170        ob[0].push_str("!");
1171        ob.push_back("b".to_string());
1172        let Json(mutation) = ob.flush().unwrap();
1173        // Element 0 has Append (not Replace), so no collapse.
1174        assert_eq!(
1175            mutation,
1176            Some(batch!(_, append!(_, json!(["b"])), append!(-2, json!("!"))))
1177        );
1178    }
1179
1180    #[test]
1181    fn no_modify_then_append() {
1182        let mut deque = VecDeque::from(["a".to_string()]);
1183        let mut ob = deque.__observe();
1184        // Access without modification.
1185        let _ = &ob[0];
1186        ob.push_back("b".to_string());
1187        let Json(mutation) = ob.flush().unwrap();
1188        assert_eq!(mutation, Some(append!(_, json!(["b"]))));
1189    }
1190
1191    #[test]
1192    fn modify_element_then_pop_back() {
1193        let mut deque = VecDeque::from(["a".to_string(), "b".to_string(), "c".to_string()]);
1194        let mut ob = deque.__observe();
1195        ob[0].push_str("!");
1196        ob.pop_back();
1197        let Json(mutation) = ob.flush().unwrap();
1198        // Element 0 has Append (not Replace), so fine-grained: truncate + element append.
1199        assert_eq!(mutation, Some(batch!(_, truncate!(_, 1), append!(-2, json!("!")))));
1200    }
1201
1202    #[test]
1203    fn index_read_only_no_mutation() {
1204        let mut deque = VecDeque::from(["hello".to_string(), "world".to_string()]);
1205        let mut ob = deque.__observe();
1206        // Read-only access through index should NOT produce mutations.
1207        let _val = &ob[0];
1208        let _val2 = &ob[1];
1209        let Json(mutation) = ob.flush().unwrap();
1210        assert_eq!(mutation, None);
1211    }
1212
1213    #[test]
1214    fn pop_push_clears_stale_observer_state() {
1215        let mut deque = VecDeque::from(["a".to_string(), "b".to_string(), "ab".to_string()]);
1216        let mut ob = deque.__observe();
1217
1218        // Modify element 2, then pop and push back in the same cycle.
1219        ob[2].truncate(1);
1220        ob.pop_back();
1221        ob.push_back("cd".to_string());
1222        let Json(mutation) = ob.flush().unwrap();
1223        assert!(mutation.is_some()); // Truncate(1) + Append(["cd"])
1224
1225        // Next cycle: element 2 should have a fresh observer.
1226        assert_eq!(ob[2], "cd");
1227        let Json(mutation) = ob.flush().unwrap();
1228        assert_eq!(mutation, None);
1229    }
1230}