Skip to main content

fbl/
doubly_linked_list.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::ptr_traits::{ManagedPtr, MutPtr, PtrTraits};
6use crate::sentinel::{is_sentinel_ptr, make_sentinel};
7use crate::size_tracker::{NonTrackingSize, SizeTracker, TrackingSize};
8use crate::tag::DefaultObjectTag;
9use core::cell::UnsafeCell;
10use core::pin::Pin;
11use pin_init::{PinInit, pin_data, pin_init, pinned_drop};
12
13/// A node in a doubly linked list.
14///
15/// Nodes are `!Unpin`: while an element is linked into a list, its neighbors hold raw pointers to
16/// it, so it must not be moved (or have its node swapped/overwritten). Containing types should mark
17/// their node field(s) with `#[pin]` when using `#[pin_data]` so that the `!Unpin`-ness propagates.
18#[repr(C)]
19pub struct DoublyLinkedListNode<T> {
20    /// The next element in the list.
21    pub next: UnsafeCell<*mut T>,
22    /// The previous element in the list.
23    pub prev: UnsafeCell<*mut T>,
24    /// Marker making the node (and any type embedding it) `!Unpin`.
25    ///
26    /// Wrapped in `PhantomData` so the node remains FFI-safe (`improper_ctypes` rejects a bare
27    /// `PhantomPinned` in `extern` signatures, but ignores `PhantomData` fields).
28    _pin: core::marker::PhantomData<core::marker::PhantomPinned>,
29}
30
31impl<T> DoublyLinkedListNode<T> {
32    /// Creates a new, unlinked node.
33    #[inline]
34    pub const fn new() -> Self {
35        Self {
36            next: UnsafeCell::new(core::ptr::null_mut()),
37            prev: UnsafeCell::new(core::ptr::null_mut()),
38            _pin: core::marker::PhantomData,
39        }
40    }
41
42    /// Returns true if the node is currently in a list.
43    #[inline]
44    pub fn in_container(&self) -> bool {
45        // SAFETY: `self.next.get()` returns a valid pointer to the inner field of `self.next`
46        // which is a validly allocated UnsafeCell inside `self`.
47        !unsafe { *self.next.get() }.is_null()
48    }
49
50    #[inline]
51    fn get_next(&self) -> *mut T {
52        // SAFETY: `self.next.get()` is a valid pointer to `self.next` which is owned by `self`.
53        unsafe { *self.next.get() }
54    }
55
56    #[inline]
57    fn set_next(&self, next: *mut T) {
58        // SAFETY: `self.next.get()` is a valid, writable pointer to `self.next` owned by `self`.
59        // UnsafeCell allows interior mutability through a shared reference.
60        unsafe {
61            *self.next.get() = next;
62        }
63    }
64
65    #[inline]
66    fn get_prev(&self) -> *mut T {
67        // SAFETY: `self.prev.get()` is a valid pointer to `self.prev` which is owned by `self`.
68        unsafe { *self.prev.get() }
69    }
70
71    #[inline]
72    fn set_prev(&self, prev: *mut T) {
73        // SAFETY: `self.prev.get()` is a valid, writable pointer to `self.prev` owned by `self`.
74        // UnsafeCell allows interior mutability through a shared reference.
75        unsafe {
76            *self.prev.get() = prev;
77        }
78    }
79}
80
81impl<T> core::fmt::Debug for DoublyLinkedListNode<T> {
82    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
83        f.debug_struct("DoublyLinkedListNode").field("in_container", &self.in_container()).finish()
84    }
85}
86
87impl<T> Default for DoublyLinkedListNode<T> {
88    #[inline]
89    fn default() -> Self {
90        Self::new()
91    }
92}
93
94impl<T> Drop for DoublyLinkedListNode<T> {
95    #[inline]
96    fn drop(&mut self) {
97        debug_assert!(!self.in_container(), "Object destroyed while still in container");
98    }
99}
100
101/// Trait that types must implement to be contained in a `DoublyLinkedList`.
102pub trait DoublyLinkedListContainable<T, Tag = DefaultObjectTag> {
103    /// Returns a reference to the list node.
104    fn get_node(&self) -> &DoublyLinkedListNode<T>;
105}
106
107/// An intrusive doubly linked list container supporting custom ownership semantics, constant-time
108/// operations, and circular-like node layout.
109///
110/// ### Bookkeeping & Memory Storage
111///
112/// The bookkeeping storage (`DoublyLinkedListNode`) required to link elements exists directly
113/// on the objects themselves. This intrusive pattern eliminates the need for runtime bookkeeping
114/// allocations/deallocations when adding or removing members to/from the container.
115///
116/// The list stores pointers to the objects, not the objects themselves, and is parameterized
117/// based on the specific pointer wrapper to be stored (`P`). Supported pointer wrappers are:
118///
119/// * `*mut T`       : Raw unmanaged pointers.
120/// * `UniquePtr<T>` : Unique managed pointers.
121/// * `RefPtr<T>`    : Shared managed pointers to reference-counted objects.
122///
123/// ### Lifecycle Management
124///
125/// * **Managed Pointers (`UniquePtr`/`RefPtr`)**: The list holds ownership references of elements
126///   and follows the rules of the respective smart pointer. Clearing the list or dropping it out of
127///   scope automatically releases references, which may destruct the elements if it was their last
128///   reference.
129///
130/// * **Unmanaged Pointers (`*mut T`)**: The list performs no lifecycle management. It is up to the
131///   caller to ensure elements outlive the list and are freed correctly. As a safety check, a list
132///   of unmanaged pointers will panic/debug-assert if it is dropped with elements still inside.
133///
134/// ### Ring Layout & Sentinel
135///
136/// Nodes are arranged in a circular-like ring structure:
137///
138/// * `head` stores a sentinel value (a pointer to the container itself) when the list is empty.
139/// * For non-empty lists, the `next` pointer of the tail node points to the sentinel, and the
140///   `prev` pointer of the head node points to the tail node. This allows constant-time O(1) tail
141///   lookup and bidirectionality.
142/// * Because the sentinel points back to the container's own memory address, the `DoublyLinkedList`
143///   container **must be pinned in memory** (typically via `pin_init::stack_pin_init!`) and cannot
144///   be safely moved after initialization.
145///
146/// ### Additional Functionality over SinglyLinkedList
147///
148/// * O(1) `push_back`, `pop_back`, and `back` operations.
149/// * The ability to `insert` (before an element) in addition to `insert_after`.
150/// * The ability to `erase` (by reference or iterator) in addition to `erase_next`.
151/// * Bidirectional iteration support.
152///
153/// ### Multiple List Participation
154///
155/// Objects may exist on multiple lists simultaneously through the use of custom `Tag` classes
156/// implementing `DoublyLinkedListContainable` multiple times.
157///
158/// ---
159///
160/// ### Example: Simple list of unmanaged raw pointers
161///
162/// ```rust
163/// # use fbl::{DoublyLinkedList, DoublyLinkedListNode, stack_pin_init, pin_init::PinInit};
164/// #[derive(fbl::DoublyLinkedListContainable)]
165/// struct Foo {
166///     value: i32,
167///     #[dll_node]
168///     node: DoublyLinkedListNode<Foo>,
169/// }
170///
171/// impl Foo {
172///     fn new(value: i32) -> Self {
173///         Self { value, node: DoublyLinkedListNode::new() }
174///     }
175/// }
176///
177/// stack_pin_init!(let list = DoublyLinkedList::<*mut Foo>::new());
178///
179/// // SAFETY: The objects are freshly allocated and are freed only after being removed.
180/// unsafe {
181///     list.as_mut().push_front_raw(Box::into_raw(Box::new(Foo::new(1))));
182///     list.as_mut().push_back_raw(Box::into_raw(Box::new(Foo::new(2))));
183/// }
184///
185/// for foo in list.iter() {
186///     println!("Value: {}", foo.value);
187/// }
188///
189/// while let Some(foo_ptr) = list.as_mut().pop_front() {
190///     // SAFETY: `foo_ptr` was created by `Box::into_raw` and is no longer in the list.
191///     let _ = unsafe { Box::from_raw(foo_ptr) };
192/// }
193/// ```
194///
195/// ### Example: Simple list of unique managed pointers
196///
197/// ```rust
198/// use fbl::{DoublyLinkedList, DoublyLinkedListNode, UniquePtr, stack_pin_init};
199///
200/// #[derive(fbl::DoublyLinkedListContainable, fbl::Recyclable)]
201/// struct Foo {
202///     value: i32,
203///     #[dll_node]
204///     node: DoublyLinkedListNode<Foo>,
205/// }
206///
207/// impl Foo {
208///     fn new(value: i32) -> Self {
209///         Self { value, node: DoublyLinkedListNode::new() }
210///     }
211/// }
212///
213/// stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<Foo>>::new());
214///
215/// list.as_mut().push_front(UniquePtr::try_new(Foo::new(1)).unwrap());
216/// list.as_mut().push_back(UniquePtr::try_new(Foo::new(2)).unwrap());
217///
218/// for foo in list.iter() {
219///     println!("Value: {}", foo.value);
220/// }
221///
222/// // Clearing the list automatically drops unique pointers and reclaims their memory!
223/// list.as_mut().clear();
224/// ```
225///
226/// ### Example: Shared objects in multiple lists simultaneously using Tags
227///
228/// ```rust
229/// use fbl::{DoublyLinkedList, DoublyLinkedListNode, RefPtr, stack_pin_init};
230///
231/// struct TagA;
232/// struct TagB;
233///
234/// #[fbl::ref_counted]
235/// #[derive(fbl::DoublyLinkedListContainable)]
236/// struct Foo {
237///     value: i32,
238///     #[dll_node(TagA)]
239///     node_a: DoublyLinkedListNode<Foo>,
240///     #[dll_node(TagB)]
241///     node_b: DoublyLinkedListNode<Foo>,
242/// }
243///
244/// stack_pin_init!(let list_a = DoublyLinkedList::<RefPtr<Foo>, TagA>::new());
245/// stack_pin_init!(let list_b = DoublyLinkedList::<RefPtr<Foo>, TagB>::new());
246///
247/// let foo = fbl::make_ref_counted!(Foo {
248///     value: 42,
249///     node_a: DoublyLinkedListNode::new(),
250///     node_b: DoublyLinkedListNode::new(),
251/// }).unwrap();
252///
253/// list_a.as_mut().push_back(foo.clone());
254/// list_b.as_mut().push_back(foo);
255/// ```
256#[repr(C)]
257#[pin_data(PinnedDrop)]
258pub struct DoublyLinkedList<P, Tag = DefaultObjectTag, S = NonTrackingSize>
259where
260    P: PtrTraits,
261    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
262    S: SizeTracker,
263{
264    /// Pointer to the first element of the list.
265    ///
266    /// # Link Structure
267    ///
268    /// Nodes in the list are arranged in a circular-like ring structure using a sentinel:
269    /// * For a non-empty list, the `next` pointer of each node points to the next element,
270    ///   and the `next` pointer of the **tail** node points to the **sentinel** (which is
271    ///   a pointer back to this `DoublyLinkedList` container itself).
272    /// * The `prev` pointer of each node points to the previous element.
273    ///
274    /// # Empty List Value
275    ///
276    /// When the list is empty, this `head` pointer holds the **sentinel** value (a pointer
277    /// to the container itself).
278    ///
279    /// # Tail Pointer Location
280    ///
281    /// The tail pointer of the list is located in the `prev` field of the **head** node's
282    /// list node (`head->prev`), which can be accessed or updated via `self.get_tail()` and
283    /// `self.set_tail()`.
284    head: *mut P::Target,
285
286    /// The size tracker for the list, supporting either O(N) or O(1) size operations
287    /// depending on the `S` parameter (e.g., `NonTrackingSize` or `TrackingSize`).
288    size: S,
289
290    /// Marker to ensure the list container is pinned in memory. Pinning is required
291    /// because the sentinel pointer points back to the container's own memory address,
292    /// meaning the list cannot be safely moved once initialized.
293    #[pin]
294    _pin: core::marker::PhantomPinned,
295
296    _phantom: core::marker::PhantomData<(P, Tag)>,
297}
298
299impl<P, Tag, S> DoublyLinkedList<P, Tag, S>
300where
301    P: PtrTraits,
302    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
303    S: SizeTracker,
304{
305    /// Creates a new, empty list.
306    #[inline]
307    pub fn new() -> impl PinInit<Self, core::convert::Infallible> {
308        pin_init!(&this in Self {
309            head: make_sentinel(this.as_ptr()),
310            size: S::INIT,
311            _pin: core::marker::PhantomPinned,
312            _phantom: core::marker::PhantomData,
313        })
314    }
315
316    #[inline]
317    fn get_sentinel(&self) -> *mut P::Target {
318        make_sentinel(self as *const Self as *mut Self)
319    }
320
321    #[inline]
322    fn get_tail(&self) -> *mut P::Target {
323        if self.is_empty() {
324            self.get_sentinel()
325        } else {
326            // SAFETY: `self.head` is a valid, aligned pointer to an element in the list.
327            // Reading `prev` from its node returns a valid pointer (either another node or
328            // sentinel).
329            unsafe { *(*self.head).get_node().prev.get() }
330        }
331    }
332
333    /// # Safety
334    ///
335    /// The caller must ensure that the list is not empty.
336    #[inline]
337    unsafe fn set_tail(&self, tail: *mut P::Target) {
338        debug_assert!(!self.is_empty());
339        // SAFETY: `self.head` is a valid, aligned pointer to an element in the list.
340        // Writing to its `prev` node UnsafeCell is safe because we have exclusive or shared access
341        // and interior mutability is allowed.
342        unsafe {
343            *(*self.head).get_node().prev.get() = tail;
344        }
345    }
346
347    /// # Safety
348    ///
349    /// The caller must ensure that `ptr` is a valid, aligned, and dereferenceable pointer
350    /// to an initialized `P::Target` object that is alive for `'a`.
351    #[inline]
352    unsafe fn get_node_ref<'a>(&self, ptr: *mut P::Target) -> &'a DoublyLinkedListNode<P::Target> {
353        let _ = self;
354        // SAFETY: The caller guarantees `ptr` is valid, aligned, and dereferenceable.
355        unsafe { &(*ptr) }.get_node()
356    }
357
358    /// Returns true if the list is empty.
359    #[inline]
360    pub fn is_empty(&self) -> bool {
361        is_sentinel_ptr(self.head)
362    }
363
364    /// Returns a reference to the first element of the list, or `None` if it is empty.
365    #[inline]
366    pub fn front(&self) -> Option<&P::Target> {
367        if self.is_empty() { None } else { unsafe { Some(&*self.head) } }
368    }
369
370    /// Returns a pinned mutable reference to the first element of the list, or `None` if it is
371    /// empty.
372    #[inline]
373    pub fn front_mut(self: Pin<&mut Self>) -> Option<Pin<&mut P::Target>>
374    where
375        P: MutPtr,
376    {
377        if self.is_empty() {
378            None
379        } else {
380            // SAFETY: `self.head` is a valid element of this list. `P: MutPtr` guarantees that
381            // exclusive access to the list implies exclusive access to its elements, and the list
382            // never moves its elements while they are linked.
383            Some(unsafe { Pin::new_unchecked(&mut *self.head) })
384        }
385    }
386
387    /// Returns a reference to the last element of the list, or `None` if it is empty.
388    #[inline]
389    pub fn back(&self) -> Option<&P::Target> {
390        let tail = self.get_tail();
391        if is_sentinel_ptr(tail) { None } else { unsafe { Some(&*tail) } }
392    }
393
394    /// Returns a pinned mutable reference to the last element of the list, or `None` if it is
395    /// empty.
396    #[inline]
397    pub fn back_mut(self: Pin<&mut Self>) -> Option<Pin<&mut P::Target>>
398    where
399        P: MutPtr,
400    {
401        let tail = self.get_tail();
402        if is_sentinel_ptr(tail) {
403            None
404        } else {
405            // SAFETY: `tail` is a valid element of this list. `P: MutPtr` guarantees that
406            // exclusive access to the list implies exclusive access to its elements, and the list
407            // never moves its elements while they are linked.
408            Some(unsafe { Pin::new_unchecked(&mut *tail) })
409        }
410    }
411
412    /// Returns a cursor positioned at `current`, which must be either a member of this list or
413    /// this list's sentinel.
414    #[inline]
415    fn cursor_at_ptr(self: Pin<&mut Self>, current: *mut P::Target) -> CursorMut<'_, P, Tag, S> {
416        CursorMut { list: self, current }
417    }
418
419    /// Pushes an element to the front of the list.
420    ///
421    /// # Panics
422    ///
423    /// Panics if the object is already in a container.
424    #[inline]
425    pub fn push_front(self: Pin<&mut Self>, ptr: P)
426    where
427        P: ManagedPtr,
428    {
429        // SAFETY: `P` is a `ManagedPtr`, which guarantees that the pointer is valid and that the
430        // object will outlive its reference from this list.
431        unsafe { self.push_front_raw(ptr) }
432    }
433
434    /// Pushes an element to the front of the list.
435    ///
436    /// # Panics
437    ///
438    /// Panics in debug builds if the object is already in a container.
439    ///
440    /// # Safety
441    ///
442    /// The caller must ensure that `ptr` is a valid pointer to a `T` that is not currently in any
443    /// list, and that the object outlives the reference from the list. If mutable element
444    /// accessors (`front_mut`, `back_mut`, `iter_mut`, `CursorMut::get_mut`, etc.) are used on a
445    /// raw-pointer list, the caller must also ensure that no other references to the element are
446    /// accessed while it is mutably borrowed through the list, and that the element satisfies
447    /// `Pin`'s drop guarantee (it is not moved out of its memory location before being dropped,
448    /// unless `P::Target: Unpin`).
449    #[inline]
450    pub unsafe fn push_front_raw(self: Pin<&mut Self>, ptr: P) {
451        let mut cursor = self.cursor_front_mut();
452        // SAFETY: `ptr` is valid and not in container (debug-asserted inside insert_before_raw).
453        unsafe {
454            cursor.insert_before_raw(ptr);
455        }
456    }
457
458    /// Pushes an element to the back of the list.
459    ///
460    /// # Panics
461    ///
462    /// Panics if the object is already in a container.
463    #[inline]
464    pub fn push_back(self: Pin<&mut Self>, ptr: P)
465    where
466        P: ManagedPtr,
467    {
468        // SAFETY: `P` is a `ManagedPtr`, which guarantees that the pointer is valid and that the
469        // object will outlive its reference from this list.
470        unsafe { self.push_back_raw(ptr) }
471    }
472
473    /// Pushes an element to the back of the list.
474    ///
475    /// # Panics
476    ///
477    /// Panics in debug builds if the object is already in a container.
478    ///
479    /// # Safety
480    ///
481    /// The caller must ensure that `ptr` is a valid pointer to an object that is not
482    /// currently in any list. If mutable element accessors (`front_mut`, `back_mut`, `iter_mut`,
483    /// `CursorMut::get_mut`, etc.) are used on a raw-pointer list, the caller must also ensure
484    /// that no other references to the element are accessed while it is mutably borrowed through
485    /// the list, and that the element satisfies `Pin`'s drop guarantee (it is not moved out of its
486    /// memory location before being dropped, unless `P::Target: Unpin`).
487    #[inline]
488    pub unsafe fn push_back_raw(self: Pin<&mut Self>, ptr: P) {
489        let mut cursor = self.cursor_back_mut();
490        // SAFETY: `ptr` is valid and not in container.
491        unsafe {
492            cursor.insert_before_raw(ptr);
493        }
494    }
495
496    /// Removes and returns the first element of the list, or `None` if it is empty.
497    #[inline]
498    pub fn pop_front(self: Pin<&mut Self>) -> Option<P> {
499        self.cursor_front_mut().erase()
500    }
501
502    /// Removes and returns the last element of the list, or `None` if it is empty.
503    #[inline]
504    pub fn pop_back(self: Pin<&mut Self>) -> Option<P> {
505        let tail = self.get_tail();
506        self.cursor_at_ptr(tail).erase()
507    }
508
509    /// Removes all elements from the list.
510    pub fn clear(mut self: Pin<&mut Self>) {
511        while self.as_mut().pop_front().is_some() {}
512    }
513
514    /// Erases the given element from the list. Returns the erased element.
515    ///
516    /// # Safety
517    ///
518    /// The caller must ensure that `obj` is a valid reference to an object that is
519    /// currently in this list instance.
520    #[inline]
521    pub unsafe fn erase(self: Pin<&mut Self>, obj: &P::Target) -> Option<P> {
522        let ptr = obj as *const P::Target as *mut P::Target;
523        let node = obj.get_node();
524
525        if !node.in_container() {
526            return None;
527        }
528
529        self.cursor_at_ptr(ptr).erase()
530    }
531
532    /// Replaces the given element with `replacement`. Returns the replaced element.
533    ///
534    /// # Safety
535    ///
536    /// The caller must ensure that `obj` is a valid reference to an object that is
537    /// currently in this list instance, and `replacement` is not in any list. If mutable element
538    /// accessors (`front_mut`, `back_mut`, `iter_mut`, `CursorMut::get_mut`, etc.) are used on a
539    /// raw-pointer list, the caller must also ensure that no other references to `replacement` are
540    /// accessed while it is mutably borrowed through the list, and that `replacement` satisfies
541    /// `Pin`'s drop guarantee (it is not moved out of its memory location before being dropped,
542    /// unless `P::Target: Unpin`).
543    #[inline]
544    pub unsafe fn replace_raw(self: Pin<&mut Self>, obj: &P::Target, replacement: P) -> Option<P> {
545        let ptr = obj as *const P::Target as *mut P::Target;
546        let node = obj.get_node();
547
548        if !node.in_container() {
549            return None;
550        }
551
552        let mut cursor = self.cursor_at_ptr(ptr);
553        // SAFETY: `replacement` is not in any list, and cursor is positioned at a valid element.
554        unsafe { cursor.replace_raw(replacement) }
555    }
556
557    /// Finds the first element matching the predicate, removes it from the list,
558    /// and returns it. Returns `None` if no element matches.
559    #[inline]
560    pub fn erase_if<F>(self: Pin<&mut Self>, mut f: F) -> Option<P>
561    where
562        F: FnMut(&P::Target) -> bool,
563    {
564        let mut cursor = self.cursor_front_mut();
565        while let Some(item) = cursor.get() {
566            if f(item) {
567                return cursor.erase();
568            } else {
569                cursor.move_next();
570            }
571        }
572        None
573    }
574
575    /// Finds the first element that satisfies the predicate.
576    #[inline]
577    pub fn find_if<F>(&self, mut f: F) -> Option<&P::Target>
578    where
579        F: FnMut(&P::Target) -> bool,
580    {
581        self.iter().find(|&x| f(x))
582    }
583
584    /// Returns a cursor positioned at the front of the list.
585    #[inline]
586    pub fn cursor_front_mut(self: Pin<&mut Self>) -> CursorMut<'_, P, Tag, S> {
587        let head = self.head;
588        self.cursor_at_ptr(head)
589    }
590
591    /// Returns a cursor positioned at the back (end sentinel) of the list.
592    #[inline]
593    pub fn cursor_back_mut(self: Pin<&mut Self>) -> CursorMut<'_, P, Tag, S> {
594        let sentinel = self.get_sentinel();
595        self.cursor_at_ptr(sentinel)
596    }
597
598    /// Returns a cursor positioned at the given element.
599    ///
600    /// # Safety
601    ///
602    /// The caller must ensure that `obj` is a member of this list.
603    /// It is undefined behavior to use the returned cursor if `obj` is not in the list,
604    /// or if it is in a different list.
605    #[inline]
606    pub unsafe fn cursor_at(self: Pin<&mut Self>, obj: &P::Target) -> CursorMut<'_, P, Tag, S> {
607        debug_assert!(obj.get_node().in_container(), "Object must be in a container");
608        self.cursor_at_ptr(obj as *const P::Target as *mut P::Target)
609    }
610
611    /// Splices all elements from `other` onto the end of `self`.
612    ///
613    /// Upon completion, `other` is left empty.
614    ///
615    /// This operation is O(1).
616    #[inline]
617    pub fn splice(self: Pin<&mut Self>, other: Pin<&mut DoublyLinkedList<P, Tag, S>>) {
618        self.cursor_back_mut().splice(other);
619    }
620
621    #[inline]
622    pub fn iter(&self) -> Iterator<'_, P, Tag> {
623        Iterator::new(self)
624    }
625
626    /// Returns a mutable bidirectional iterator over the elements of the list.
627    ///
628    /// Elements are yielded as `Pin<&mut P::Target>` since they must not be moved while linked.
629    #[inline]
630    pub fn iter_mut(self: Pin<&mut Self>) -> IteratorMut<'_, P, Tag>
631    where
632        P: MutPtr,
633    {
634        IteratorMut::new(self)
635    }
636
637    /// Returns a unidirectional forward iterator over the elements of the list.
638    #[inline]
639    pub fn forward_iter(&self) -> ForwardIterator<'_, P, Tag> {
640        ForwardIterator::new(self.head)
641    }
642
643    /// Returns a unidirectional forward mutable iterator over the elements of the list.
644    ///
645    /// Elements are yielded as `Pin<&mut P::Target>` since they must not be moved while linked.
646    #[inline]
647    pub fn forward_iter_mut(self: Pin<&mut Self>) -> ForwardIteratorMut<'_, P, Tag>
648    where
649        P: MutPtr,
650    {
651        ForwardIteratorMut::new(self.head)
652    }
653
654    /// Returns a unidirectional reverse iterator over the elements of the list.
655    #[inline]
656    pub fn reverse_iter(&self) -> ReverseIterator<'_, P, Tag> {
657        ReverseIterator::new(self.get_tail())
658    }
659
660    /// Returns a unidirectional reverse mutable iterator over the elements of the list.
661    ///
662    /// Elements are yielded as `Pin<&mut P::Target>` since they must not be moved while linked.
663    #[inline]
664    pub fn reverse_iter_mut(self: Pin<&mut Self>) -> ReverseIteratorMut<'_, P, Tag>
665    where
666        P: MutPtr,
667    {
668        ReverseIteratorMut::new(self.get_tail(), self.head)
669    }
670}
671
672impl<P, Tag> DoublyLinkedList<P, Tag, TrackingSize>
673where
674    P: PtrTraits,
675    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
676{
677    /// Returns the number of elements in the list.
678    #[inline]
679    pub fn len(&self) -> usize {
680        self.size.get()
681    }
682}
683
684#[pinned_drop]
685impl<P, Tag, S> PinnedDrop for DoublyLinkedList<P, Tag, S>
686where
687    P: PtrTraits,
688    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
689    S: SizeTracker,
690{
691    fn drop(self: Pin<&mut Self>) {
692        if P::IS_MANAGED {
693            self.clear();
694        } else {
695            debug_assert!(self.is_empty(), "List must be empty on destruction");
696            if S::IS_TRACKING {
697                debug_assert_eq!(self.size.get(), 0, "Size must be zero on destruction");
698            }
699        }
700    }
701}
702
703/// A cursor that can be used to iterate and modify a `DoublyLinkedList`.
704///
705/// The cursor holds the list as `Pin<&mut DoublyLinkedList>` and mutates the list's `head` and
706/// `size` fields through pin projection, so an unpinned `&mut DoublyLinkedList` is never
707/// materialized.
708pub struct CursorMut<'a, P, Tag = DefaultObjectTag, S = NonTrackingSize>
709where
710    P: PtrTraits,
711    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
712    S: SizeTracker,
713{
714    list: Pin<&'a mut DoublyLinkedList<P, Tag, S>>,
715    current: *mut P::Target,
716}
717
718impl<'a, P, Tag, S> CursorMut<'a, P, Tag, S>
719where
720    P: PtrTraits,
721    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
722    S: SizeTracker,
723{
724    #[inline]
725    pub fn get(&self) -> Option<&P::Target> {
726        if is_sentinel_ptr(self.current) { None } else { unsafe { Some(&*self.current) } }
727    }
728
729    /// Returns a pinned mutable reference to the element at the current position, or `None` if
730    /// the cursor is positioned at the end sentinel.
731    #[inline]
732    pub fn get_mut(&mut self) -> Option<Pin<&mut P::Target>>
733    where
734        P: MutPtr,
735    {
736        if is_sentinel_ptr(self.current) {
737            None
738        } else {
739            // SAFETY: `self.current` is a valid element of the list (not the sentinel). `P: MutPtr`
740            // guarantees that exclusive access to the list (held by this cursor) implies exclusive
741            // access to its elements, and the list never moves its elements while they are linked.
742            Some(unsafe { Pin::new_unchecked(&mut *self.current) })
743        }
744    }
745
746    #[inline]
747    pub fn move_next(&mut self) {
748        if !is_sentinel_ptr(self.current) {
749            // SAFETY: `self.current` is valid current node (not sentinel).
750            let node = unsafe { self.list.get_node_ref(self.current) };
751            self.current = node.get_next();
752        }
753    }
754
755    #[inline]
756    pub fn move_prev(&mut self) {
757        if !is_sentinel_ptr(self.current) {
758            // SAFETY: `self.current` is valid current node (not sentinel).
759            let node = unsafe { self.list.get_node_ref(self.current) };
760            let prev = node.get_prev();
761            if self.current == self.list.head {
762                self.current = self.list.get_sentinel(); // Move to end.
763            } else {
764                self.current = prev;
765            }
766        } else {
767            // If we are at end (sentinel), moving prev should take us to tail.
768            self.current = self.list.get_tail();
769        }
770    }
771
772    /// Inserts a new element after the current position.
773    ///
774    /// # Panics
775    ///
776    /// Panics if the object is already in a container, or if the cursor is positioned
777    /// at the end sentinel.
778    #[inline]
779    pub fn insert_after(&mut self, ptr: P)
780    where
781        P: ManagedPtr,
782    {
783        debug_assert!(!ptr.get_ref().get_node().in_container());
784        // SAFETY: `P` is a `ManagedPtr`, which guarantees that the pointer is valid and that the
785        // object will outlive its reference from this list. `self.current` is checked to not be
786        // a sentinel.
787        unsafe { self.insert_after_raw(ptr) }
788    }
789
790    /// Inserts a new element after the current position.
791    ///
792    /// # Panics
793    ///
794    /// Panics if the cursor is positioned at the end sentinel, or in debug builds if the object is
795    /// already in a container.
796    ///
797    /// # Safety
798    ///
799    /// The caller must ensure that `ptr` is a valid pointer to a `T` that is not currently in any
800    /// list, and that the object outlives the reference from the list. If mutable element
801    /// accessors (`front_mut`, `back_mut`, `iter_mut`, `CursorMut::get_mut`, etc.) are used on a
802    /// raw-pointer list, the caller must also ensure that no other references to the element are
803    /// accessed while it is mutably borrowed through the list, and that the element satisfies
804    /// `Pin`'s drop guarantee (it is not moved out of its memory location before being dropped,
805    /// unless `P::Target: Unpin`).
806    #[inline]
807    pub unsafe fn insert_after_raw(&mut self, ptr: P) {
808        debug_assert!(!is_sentinel_ptr(self.current), "Cannot insert after end sentinel");
809        let raw = P::into_raw(ptr);
810        // SAFETY: `raw` is valid.
811        let node = unsafe { self.list.get_node_ref(raw) };
812        debug_assert!(!node.in_container());
813
814        // SAFETY: `self.current` is valid current node (not sentinel).
815        let current_node = unsafe { self.list.get_node_ref(self.current) };
816        let next = current_node.get_next();
817
818        let current_save = self.current;
819        self.current = next;
820        // SAFETY: `raw` is a single node, and we are inserting it before `next`
821        // (which is equivalent to inserting after `current_save`).
822        unsafe {
823            self.insert_chain_before(raw, raw, 1);
824        }
825        self.current = current_save;
826    }
827
828    /// Replaces the element at the current position with `replacement`. Returns the replaced
829    /// element.
830    ///
831    /// # Panics
832    ///
833    /// Panics if the object is already in a container.
834    #[inline]
835    pub fn replace(&mut self, replacement: P) -> Option<P>
836    where
837        P: ManagedPtr,
838    {
839        // SAFETY: `P` is a `ManagedPtr`, which guarantees that the pointer is valid and that the
840        // object will outlive its reference from this list.
841        unsafe { self.replace_raw(replacement) }
842    }
843
844    /// Replaces the element at the current position with `replacement`. Returns the replaced
845    /// element.
846    ///
847    /// # Panics
848    ///
849    /// Panics in debug builds if the object is already in a container.
850    ///
851    /// # Safety
852    ///
853    /// The caller must ensure that `replacement` is a valid pointer to a `T` that is not currently
854    /// in any list, and that the object outlives the reference from the list. If mutable element
855    /// accessors (`front_mut`, `back_mut`, `iter_mut`, `CursorMut::get_mut`, etc.) are used on a
856    /// raw-pointer list, the caller must also ensure that no other references to `replacement` are
857    /// accessed while it is mutably borrowed through the list, and that `replacement` satisfies
858    /// `Pin`'s drop guarantee (it is not moved out of its memory location before being dropped,
859    /// unless `P::Target: Unpin`).
860    #[inline]
861    pub unsafe fn replace_raw(&mut self, replacement: P) -> Option<P> {
862        if is_sentinel_ptr(self.current) {
863            return None;
864        }
865        // SAFETY: `replacement` is not in any list, and we are inserting it before a valid cursor
866        // position.
867        unsafe {
868            self.insert_before_raw(replacement);
869        }
870        self.erase()
871    }
872
873    /// Inserts a new element before the current position.
874    ///
875    /// # Panics
876    ///
877    /// Panics if the object is already in a container.
878    #[inline]
879    pub fn insert_before(&mut self, ptr: P)
880    where
881        P: ManagedPtr,
882    {
883        debug_assert!(!ptr.get_ref().get_node().in_container());
884        // SAFETY: `P` is a `ManagedPtr`, which guarantees that the pointer is valid and that the
885        // object will outlive its reference from this list.
886        unsafe { self.insert_before_raw(ptr) }
887    }
888
889    /// Inserts a new element before the current position.
890    ///
891    /// # Panics
892    ///
893    /// Panics in debug builds if the object is already in a container.
894    ///
895    /// # Safety
896    ///
897    /// The caller must ensure that `ptr` is a valid pointer to a `T` that is not currently in any
898    /// list, and that the object outlives the reference from the list. If mutable element
899    /// accessors (`front_mut`, `back_mut`, `iter_mut`, `CursorMut::get_mut`, etc.) are used on a
900    /// raw-pointer list, the caller must also ensure that no other references to the element are
901    /// accessed while it is mutably borrowed through the list, and that the element satisfies
902    /// `Pin`'s drop guarantee (it is not moved out of its memory location before being dropped,
903    /// unless `P::Target: Unpin`).
904    #[inline]
905    pub unsafe fn insert_before_raw(&mut self, ptr: P) {
906        let raw = P::into_raw(ptr);
907        // SAFETY: `raw` is valid.
908        let node = unsafe { self.list.get_node_ref(raw) };
909        debug_assert!(!node.in_container());
910
911        // SAFETY: `raw` is a single node, so it is a valid chain of 1 element.
912        unsafe {
913            self.insert_chain_before(raw, raw, 1);
914        }
915    }
916
917    /// Private helper to insert a chain of nodes before the current position.
918    ///
919    /// # Safety
920    ///
921    /// The caller must ensure:
922    /// - `chain_head` and `chain_tail` are valid pointers to elements.
923    /// - They form a valid doubly linked chain.
924    /// - The chain is not empty.
925    /// - The elements in the chain are NOT currently in any list.
926    /// - `count` is the exact number of elements in the chain.
927    #[inline]
928    unsafe fn insert_chain_before(
929        &mut self,
930        chain_head: *mut P::Target,
931        chain_tail: *mut P::Target,
932        count: usize,
933    ) {
934        let head = self.list.head;
935        let before = self.current;
936        // SAFETY: `chain_tail` is valid from caller.
937        let chain_tail_node = unsafe { self.list.get_node_ref(chain_tail) };
938        // SAFETY: `chain_head` is valid from caller.
939        let chain_head_node = unsafe { self.list.get_node_ref(chain_head) };
940
941        if is_sentinel_ptr(head) {
942            chain_tail_node.set_next(before);
943            chain_head_node.set_prev(chain_tail);
944            *self.list.as_mut().project().head = chain_head;
945        } else if before == head {
946            // SAFETY: `head` is not a sentinel, so it is a valid node.
947            let head_node = unsafe { self.list.get_node_ref(head) };
948            let tail = head_node.get_prev();
949            chain_tail_node.set_next(before);
950            chain_head_node.set_prev(tail);
951            head_node.set_prev(chain_tail);
952            *self.list.as_mut().project().head = chain_head;
953        } else if is_sentinel_ptr(before) {
954            // SAFETY: `head` is not a sentinel, so it is a valid node.
955            let head_node = unsafe { self.list.get_node_ref(head) };
956            let tail = head_node.get_prev();
957            // SAFETY: `tail` is a valid node in a non-empty list.
958            let tail_node = unsafe { self.list.get_node_ref(tail) };
959            chain_tail_node.set_next(before);
960            chain_head_node.set_prev(tail);
961            tail_node.set_next(chain_head);
962            head_node.set_prev(chain_tail);
963        } else {
964            // SAFETY: `before` is not a sentinel, so it is a valid node.
965            let current_node = unsafe { self.list.get_node_ref(before) };
966            let prev = current_node.get_prev();
967            // SAFETY: `prev` is a valid predecessor node.
968            let prev_node = unsafe { self.list.get_node_ref(prev) };
969            chain_tail_node.set_next(before);
970            chain_head_node.set_prev(prev);
971            prev_node.set_next(chain_head);
972            current_node.set_prev(chain_tail);
973        }
974
975        if S::IS_TRACKING {
976            let new_size = self.list.size.get() + count;
977            self.list.as_mut().project().size.set(new_size);
978        }
979    }
980
981    /// Splices the elements of `other` into the list at the current cursor position.
982    ///
983    /// All elements from `other` are moved into `self.list` and inserted immediately
984    /// *before* the element currently pointed to by the cursor.
985    ///
986    /// - If the cursor is positioned at a valid element, `other` is inserted before it.
987    /// - If the cursor is positioned at the end sentinel (i.e., `cursor.get()` returns `None`),
988    ///   `other` is appended to the end of the list (after the current tail).
989    /// - If the list is empty, `other` becomes the new content of the list.
990    ///
991    /// Upon completion, `other` is left empty.
992    ///
993    /// This operation is O(1).
994    pub fn splice(&mut self, other: Pin<&mut DoublyLinkedList<P, Tag, S>>) {
995        if other.is_empty() {
996            return;
997        }
998
999        let other_head = other.head;
1000        let other_tail = other.get_tail();
1001        let other_sentinel = other.get_sentinel();
1002        let count = if S::IS_TRACKING { other.size.get() } else { 0 };
1003
1004        // SAFETY: We are moving elements from `other` which is a valid list,
1005        // so they are valid and not in any other list.
1006        unsafe {
1007            self.insert_chain_before(other_head, other_tail, count);
1008        }
1009
1010        let other = other.project();
1011        *other.head = other_sentinel;
1012        if S::IS_TRACKING {
1013            other.size.set(0);
1014        }
1015    }
1016
1017    /// Splits the list immediately after the current cursor position, moving all elements
1018    /// after the cursor into `dest`, inserted before `dest`'s current position.
1019    ///
1020    /// The current list retains all elements up to and including the current element.
1021    ///
1022    /// If the cursor is positioned at the tail of the list, no elements are moved.
1023    ///
1024    /// # Panics
1025    ///
1026    /// Panics if the cursor is positioned at the end sentinel.
1027    ///
1028    /// This operation is O(1) for lists with non-tracking size.
1029    pub fn split_after(&mut self, dest: &mut CursorMut<'_, P, Tag, S>) {
1030        debug_assert!(!is_sentinel_ptr(self.current), "Cannot split after end sentinel");
1031
1032        // SAFETY: `self.current` is not sentinel.
1033        let curr_node = unsafe { self.list.get_node_ref(self.current) };
1034        let next_ptr = curr_node.get_next();
1035
1036        // If cursor is at the tail, there are no elements after it.
1037        if is_sentinel_ptr(next_ptr) {
1038            return;
1039        }
1040
1041        let chain_head = next_ptr;
1042        let chain_tail = self.list.get_tail();
1043
1044        let mut count = 0;
1045        if S::IS_TRACKING {
1046            let mut p = chain_head;
1047            let sentinel = self.list.get_sentinel();
1048            while p != sentinel {
1049                count += 1;
1050                // SAFETY: `p` is in the chain.
1051                p = unsafe { self.list.get_node_ref(p) }.get_next();
1052            }
1053            let new_size = self.list.size.get() - count;
1054            self.list.as_mut().project().size.set(new_size);
1055        }
1056
1057        // Update self.list: `self.current` becomes the new tail.
1058        curr_node.set_next(self.list.get_sentinel());
1059        unsafe {
1060            self.list.set_tail(self.current);
1061        }
1062
1063        // Insert the extracted chain before dest's current position.
1064        // SAFETY: The chain [chain_head .. chain_tail] is valid, detached from self.list,
1065        // and count is exact.
1066        unsafe {
1067            dest.insert_chain_before(chain_head, chain_tail, count);
1068        }
1069    }
1070
1071    /// Splits the list immediately before the current cursor position, moving all elements
1072    /// before the cursor into `dest`, inserted before `dest`'s current position.
1073    ///
1074    /// The current list retains all elements from the current position to the end of the list.
1075    ///
1076    /// - If the cursor is positioned at the head of the list, no elements are moved.
1077    /// - If the cursor is positioned at the end sentinel, all elements of the list are moved
1078    ///   into `dest`, leaving this list empty.
1079    /// - If the cursor is positioned at an element between head and sentinel, all elements from
1080    ///   head up to (and excluding) the current element are moved into `dest`.
1081    ///
1082    /// Upon completion, the cursor remains positioned at the same element (which is now the new
1083    /// head of this list, or the sentinel).
1084    ///
1085    /// This operation is O(1) for lists with non-tracking size.
1086    pub fn split_before(&mut self, dest: &mut CursorMut<'_, P, Tag, S>) {
1087        // Case 1: Cursor is at head. No elements before head.
1088        if self.current == self.list.head {
1089            return;
1090        }
1091
1092        // Case 2: Cursor is at sentinel. All elements in list are before sentinel.
1093        if is_sentinel_ptr(self.current) {
1094            if self.list.is_empty() {
1095                return;
1096            }
1097            let chain_head = self.list.head;
1098            let chain_tail = self.list.get_tail();
1099            let sentinel = self.list.get_sentinel();
1100            let list = self.list.as_mut().project();
1101            let count = if S::IS_TRACKING {
1102                let c = list.size.get();
1103                list.size.set(0);
1104                c
1105            } else {
1106                0
1107            };
1108
1109            *list.head = sentinel;
1110
1111            // SAFETY: The chain [chain_head .. chain_tail] is valid, detached from self.list,
1112            // and count is exact.
1113            unsafe {
1114                dest.insert_chain_before(chain_head, chain_tail, count);
1115            }
1116            return;
1117        }
1118
1119        // Case 3: Cursor is at an interior element B.
1120        // Elements before B are [head .. B.prev].
1121        let b = self.current;
1122        let b_node = unsafe { self.list.get_node_ref(b) };
1123        let chain_head = self.list.head;
1124        let chain_tail = b_node.get_prev();
1125        let old_tail = self.list.get_tail();
1126
1127        let mut count = 0;
1128        if S::IS_TRACKING {
1129            let mut p = chain_head;
1130            while p != b {
1131                count += 1;
1132                // SAFETY: `p` is in the chain.
1133                p = unsafe { self.list.get_node_ref(p) }.get_next();
1134            }
1135            let new_size = self.list.size.get() - count;
1136            self.list.as_mut().project().size.set(new_size);
1137        }
1138
1139        // Update self.list: B becomes the new head, and its prev points to old_tail.
1140        *self.list.as_mut().project().head = b;
1141        b_node.set_prev(old_tail);
1142
1143        // Insert the extracted chain before dest's current position.
1144        // SAFETY: The chain [chain_head .. chain_tail] is valid, detached from self.list,
1145        // and count is exact.
1146        unsafe {
1147            dest.insert_chain_before(chain_head, chain_tail, count);
1148        }
1149    }
1150
1151    #[inline]
1152    pub fn erase(&mut self) -> Option<P> {
1153        let ptr = self.current;
1154        if is_sentinel_ptr(ptr) {
1155            return None;
1156        }
1157        let head = self.list.head;
1158        // SAFETY: `ptr` is valid current node.
1159        let node = unsafe { self.list.get_node_ref(ptr) };
1160        let next = node.get_next();
1161        let prev = node.get_prev();
1162
1163        self.list.as_mut().project().size.decrement();
1164
1165        let tgt_prev_node = if is_sentinel_ptr(next) { head } else { next };
1166        // SAFETY: Both `head` and `next` (when not sentinel) are valid nodes in a non-empty list.
1167        unsafe { self.list.get_node_ref(tgt_prev_node) }.set_prev(prev);
1168
1169        if ptr == head {
1170            *self.list.as_mut().project().head = next;
1171        } else {
1172            // SAFETY: `prev` is a valid predecessor node.
1173            unsafe { self.list.get_node_ref(prev) }.set_next(next);
1174        }
1175
1176        node.set_prev(core::ptr::null_mut());
1177        node.set_next(core::ptr::null_mut());
1178
1179        self.current = next;
1180        // SAFETY: `ptr` was popped, safe to reconstruct.
1181        Some(unsafe { P::from_raw(ptr) })
1182    }
1183}
1184
1185/// An iterator over the elements of a `DoublyLinkedList`.
1186pub struct Iterator<'a, P, Tag = DefaultObjectTag>
1187where
1188    P: PtrTraits,
1189    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1190{
1191    front: ForwardIterator<'a, P, Tag>,
1192    back: ReverseIterator<'a, P, Tag>,
1193}
1194
1195impl<'a, P, Tag> Iterator<'a, P, Tag>
1196where
1197    P: PtrTraits,
1198    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1199{
1200    fn new<S: SizeTracker>(list: &'a DoublyLinkedList<P, Tag, S>) -> Self {
1201        if list.is_empty() {
1202            Self {
1203                front: ForwardIterator::new(crate::make_sentinel_null()),
1204                back: ReverseIterator::new(crate::make_sentinel_null()),
1205            }
1206        } else {
1207            Self {
1208                front: ForwardIterator::new(list.head),
1209                back: ReverseIterator::new(list.get_tail()),
1210            }
1211        }
1212    }
1213}
1214
1215impl<'a, P, Tag> core::iter::Iterator for Iterator<'a, P, Tag>
1216where
1217    P: PtrTraits,
1218    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1219{
1220    type Item = &'a P::Target;
1221
1222    fn next(&mut self) -> Option<Self::Item> {
1223        let met = self.front.current == self.back.current;
1224        let item = self.front.next();
1225        if item.is_some() && met {
1226            self.front.current = crate::make_sentinel_null();
1227            self.back.current = crate::make_sentinel_null();
1228        }
1229        item
1230    }
1231}
1232
1233impl<'a, P, Tag> core::iter::DoubleEndedIterator for Iterator<'a, P, Tag>
1234where
1235    P: PtrTraits,
1236    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1237{
1238    fn next_back(&mut self) -> Option<Self::Item> {
1239        let met = self.front.current == self.back.current;
1240        let item = self.back.next();
1241        if item.is_some() && met {
1242            self.front.current = crate::make_sentinel_null();
1243            self.back.current = crate::make_sentinel_null();
1244        }
1245        item
1246    }
1247}
1248
1249/// A unidirectional forward iterator over the elements of a `DoublyLinkedList`.
1250pub struct ForwardIterator<'a, P, Tag = DefaultObjectTag>
1251where
1252    P: PtrTraits,
1253    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1254{
1255    current: *mut P::Target,
1256    _phantom: core::marker::PhantomData<&'a (P, Tag)>,
1257}
1258
1259impl<'a, P, Tag> ForwardIterator<'a, P, Tag>
1260where
1261    P: PtrTraits,
1262    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1263{
1264    fn new(current: *mut P::Target) -> Self {
1265        Self { current, _phantom: core::marker::PhantomData }
1266    }
1267}
1268
1269impl<'a, P, Tag> core::iter::Iterator for ForwardIterator<'a, P, Tag>
1270where
1271    P: PtrTraits,
1272    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1273{
1274    type Item = &'a P::Target;
1275
1276    fn next(&mut self) -> Option<Self::Item> {
1277        if is_sentinel_ptr(self.current) {
1278            None
1279        } else {
1280            // SAFETY: `self.current` is not a sentinel, so it is a valid, aligned pointer to an
1281            // element.  The list is guaranteed to be immutable for the lifetime `'a` of the
1282            // iterator.
1283            let current = unsafe { &*self.current };
1284            self.current = current.get_node().get_next();
1285            Some(current)
1286        }
1287    }
1288}
1289
1290/// A unidirectional reverse iterator over the elements of a `DoublyLinkedList`.
1291pub struct ReverseIterator<'a, P, Tag = DefaultObjectTag>
1292where
1293    P: PtrTraits,
1294    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1295{
1296    current: *mut P::Target,
1297    _phantom: core::marker::PhantomData<&'a (P, Tag)>,
1298}
1299
1300impl<'a, P, Tag> ReverseIterator<'a, P, Tag>
1301where
1302    P: PtrTraits,
1303    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1304{
1305    fn new(current: *mut P::Target) -> Self {
1306        Self { current, _phantom: core::marker::PhantomData }
1307    }
1308}
1309
1310impl<'a, P, Tag> core::iter::Iterator for ReverseIterator<'a, P, Tag>
1311where
1312    P: PtrTraits,
1313    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1314{
1315    type Item = &'a P::Target;
1316
1317    fn next(&mut self) -> Option<Self::Item> {
1318        if is_sentinel_ptr(self.current) {
1319            None
1320        } else {
1321            // SAFETY: `self.current` is not a sentinel, so it is a valid, aligned pointer to an
1322            // element.  The list is guaranteed to be immutable for the lifetime `'a` of the
1323            // iterator.
1324            let current = unsafe { &*self.current };
1325            let prev = current.get_node().get_prev();
1326
1327            // SAFETY: `prev` must be a valid pointer because `current` is in the list.  In a
1328            // circular doubly linked list, prev is never null.
1329            let prev_node = unsafe { &*prev }.get_node();
1330            if is_sentinel_ptr(prev_node.get_next()) {
1331                // We have looped around the head and landed on the tail.
1332                // Set current to the sentinel to terminate iteration.
1333                self.current = prev_node.get_next();
1334            } else {
1335                self.current = prev;
1336            }
1337            Some(current)
1338        }
1339    }
1340}
1341
1342/// A mutable bidirectional iterator over the elements of a `DoublyLinkedList`.
1343///
1344/// Elements are yielded as `Pin<&mut P::Target>` since they must not be moved while linked.
1345pub struct IteratorMut<'a, P, Tag = DefaultObjectTag>
1346where
1347    P: MutPtr,
1348    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1349{
1350    front: ForwardIteratorMut<'a, P, Tag>,
1351    back: ReverseIteratorMut<'a, P, Tag>,
1352}
1353
1354impl<'a, P, Tag> IteratorMut<'a, P, Tag>
1355where
1356    P: MutPtr,
1357    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1358{
1359    fn new<S: SizeTracker>(list: Pin<&'a mut DoublyLinkedList<P, Tag, S>>) -> Self {
1360        if list.is_empty() {
1361            Self {
1362                front: ForwardIteratorMut::new(crate::make_sentinel_null()),
1363                back: ReverseIteratorMut::new(
1364                    crate::make_sentinel_null(),
1365                    crate::make_sentinel_null(),
1366                ),
1367            }
1368        } else {
1369            let tail = list.get_tail();
1370            Self {
1371                front: ForwardIteratorMut::new(list.head),
1372                back: ReverseIteratorMut::new(tail, list.head),
1373            }
1374        }
1375    }
1376}
1377
1378impl<'a, P, Tag> core::iter::Iterator for IteratorMut<'a, P, Tag>
1379where
1380    P: MutPtr,
1381    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1382{
1383    type Item = Pin<&'a mut P::Target>;
1384
1385    fn next(&mut self) -> Option<Self::Item> {
1386        let met = self.front.current == self.back.current;
1387        let item = self.front.next();
1388        if item.is_some() && met {
1389            self.front.current = crate::make_sentinel_null();
1390            self.back.current = crate::make_sentinel_null();
1391        }
1392        item
1393    }
1394}
1395
1396impl<'a, P, Tag> core::iter::DoubleEndedIterator for IteratorMut<'a, P, Tag>
1397where
1398    P: MutPtr,
1399    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1400{
1401    fn next_back(&mut self) -> Option<Self::Item> {
1402        let met = self.front.current == self.back.current;
1403        let item = self.back.next();
1404        if item.is_some() && met {
1405            self.front.current = crate::make_sentinel_null();
1406            self.back.current = crate::make_sentinel_null();
1407        }
1408        item
1409    }
1410}
1411
1412/// A unidirectional forward mutable iterator over the elements of a `DoublyLinkedList`.
1413///
1414/// Elements are yielded as `Pin<&mut P::Target>` since they must not be moved while linked.
1415pub struct ForwardIteratorMut<'a, P, Tag = DefaultObjectTag>
1416where
1417    P: MutPtr,
1418    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1419{
1420    current: *mut P::Target,
1421    _phantom: core::marker::PhantomData<&'a mut (P, Tag)>,
1422}
1423
1424impl<'a, P, Tag> ForwardIteratorMut<'a, P, Tag>
1425where
1426    P: MutPtr,
1427    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1428{
1429    fn new(current: *mut P::Target) -> Self {
1430        Self { current, _phantom: core::marker::PhantomData }
1431    }
1432}
1433
1434impl<'a, P, Tag> core::iter::Iterator for ForwardIteratorMut<'a, P, Tag>
1435where
1436    P: MutPtr,
1437    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1438{
1439    type Item = Pin<&'a mut P::Target>;
1440
1441    fn next(&mut self) -> Option<Self::Item> {
1442        if is_sentinel_ptr(self.current) {
1443            None
1444        } else {
1445            let current_ptr = self.current;
1446            // SAFETY: `current_ptr` is not a sentinel, so it is a valid, aligned pointer to an
1447            // element. No mutable reference to it is live yet.
1448            self.current = unsafe { &*current_ptr }.get_node().get_next();
1449            // SAFETY: `current_ptr` is a valid element. The list is exclusively borrowed for
1450            // lifetime `'a`, `P: MutPtr` guarantees that this implies exclusive access to its
1451            // elements, and each element in the intrusive list is distinct, so yielding
1452            // `&'a mut P::Target` one-by-one is sound. The list never moves its elements while
1453            // they are linked.
1454            Some(unsafe { Pin::new_unchecked(&mut *current_ptr) })
1455        }
1456    }
1457}
1458
1459/// A unidirectional reverse mutable iterator over the elements of a `DoublyLinkedList`.
1460///
1461/// Elements are yielded as `Pin<&mut P::Target>` since they must not be moved while linked.
1462pub struct ReverseIteratorMut<'a, P, Tag = DefaultObjectTag>
1463where
1464    P: MutPtr,
1465    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1466{
1467    current: *mut P::Target,
1468    head: *mut P::Target,
1469    _phantom: core::marker::PhantomData<&'a mut (P, Tag)>,
1470}
1471
1472impl<'a, P, Tag> ReverseIteratorMut<'a, P, Tag>
1473where
1474    P: MutPtr,
1475    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1476{
1477    fn new(current: *mut P::Target, head: *mut P::Target) -> Self {
1478        Self { current, head, _phantom: core::marker::PhantomData }
1479    }
1480}
1481
1482impl<'a, P, Tag> core::iter::Iterator for ReverseIteratorMut<'a, P, Tag>
1483where
1484    P: MutPtr,
1485    P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1486{
1487    type Item = Pin<&'a mut P::Target>;
1488
1489    fn next(&mut self) -> Option<Self::Item> {
1490        if is_sentinel_ptr(self.current) {
1491            None
1492        } else {
1493            let current_ptr = self.current;
1494            if current_ptr == self.head {
1495                self.current = crate::make_sentinel_null();
1496            } else {
1497                // SAFETY: `current_ptr` is not a sentinel, so it is a valid, aligned pointer to an
1498                // element. No mutable reference to it is live yet.
1499                self.current = unsafe { &*current_ptr }.get_node().get_prev();
1500            }
1501            // SAFETY: `current_ptr` is a valid element. The list is exclusively borrowed for
1502            // lifetime `'a`, `P: MutPtr` guarantees that this implies exclusive access to its
1503            // elements, and each element in the intrusive list is distinct, so yielding
1504            // `&'a mut P::Target` one-by-one is sound. The list never moves its elements while
1505            // they are linked.
1506            Some(unsafe { Pin::new_unchecked(&mut *current_ptr) })
1507        }
1508    }
1509}
1510
1511/// Removes an object from its container without a reference to the container.
1512///
1513/// # Safety
1514///
1515/// The caller must ensure that `obj` is currently in a valid list instance that does NOT
1516/// track its size (uses `NonTrackingSize`), and that no other mutable references to that
1517/// list are active.
1518#[inline]
1519pub unsafe fn remove_from_container<T, Tag, P>(obj: &T) -> Option<P>
1520where
1521    P: PtrTraits<Target = T>,
1522    T: DoublyLinkedListContainable<T, Tag>,
1523{
1524    let node = obj.get_node();
1525    let next = node.get_next();
1526    if next.is_null() {
1527        return None;
1528    }
1529    let prev = node.get_prev();
1530    debug_assert!(!prev.is_null());
1531
1532    // SAFETY: Caller guarantees `obj` is in a valid untracked list and no other references to the
1533    // list are active.
1534    unsafe {
1535        let tgt_prev = if is_sentinel_ptr(next) {
1536            let list_ptr = crate::sentinel::unmake_sentinel::<
1537                DoublyLinkedList<P, Tag, NonTrackingSize>,
1538                T,
1539            >(next);
1540            (*(*list_ptr).head).get_node().prev.get()
1541        } else {
1542            (*next).get_node().prev.get()
1543        };
1544
1545        let prev_node = (*prev).get_node();
1546        let prev_next = prev_node.get_next();
1547        let tgt_next = if is_sentinel_ptr(prev_next) {
1548            let list_ptr = crate::sentinel::unmake_sentinel::<
1549                DoublyLinkedList<P, Tag, NonTrackingSize>,
1550                T,
1551            >(prev_next);
1552            &raw mut (*list_ptr).head
1553        } else {
1554            prev_node.next.get()
1555        };
1556
1557        *tgt_prev = prev;
1558        *tgt_next = next;
1559
1560        node.set_next(core::ptr::null_mut());
1561        node.set_prev(core::ptr::null_mut());
1562
1563        Some(P::from_raw(obj as *const T as *mut T))
1564    }
1565}
1566
1567impl<P, Tag, S> core::fmt::Debug for DoublyLinkedList<P, Tag, S>
1568where
1569    P: PtrTraits,
1570    P::Target: DoublyLinkedListContainable<P::Target, Tag> + core::fmt::Debug,
1571    S: SizeTracker,
1572{
1573    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1574        f.debug_list().entries(self.iter()).finish()
1575    }
1576}
1577
1578#[cfg(test)]
1579mod tests {
1580    extern crate alloc;
1581    use super::*;
1582    use crate::intrusive_container_test_support::*;
1583    use crate::ref_ptr::RefPtr;
1584    use crate::unique_ptr::UniquePtr;
1585    use core::ffi::c_void;
1586    use pin_init::stack_pin_init;
1587
1588    #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
1589    #[pin_data]
1590    struct TestObject {
1591        value: i32,
1592        #[pin]
1593        #[dll_node]
1594        node: DoublyLinkedListNode<TestObject>,
1595    }
1596
1597    impl TestObject {
1598        fn new(value: i32) -> Self {
1599            Self { value, node: DoublyLinkedListNode::new() }
1600        }
1601    }
1602
1603    impl TestValue for TestObject {
1604        fn new(value: i32) -> Self {
1605            Self::new(value)
1606        }
1607    }
1608
1609    ::zr::static_assert!(
1610        core::mem::size_of::<DoublyLinkedListNode<TestObject>>()
1611            == 2 * core::mem::size_of::<*mut TestObject>()
1612    );
1613    ::zr::static_assert!(
1614        core::mem::align_of::<DoublyLinkedListNode<TestObject>>()
1615            == core::mem::align_of::<*mut TestObject>()
1616    );
1617
1618    ::zr::static_assert!(
1619        core::mem::size_of::<DoublyLinkedList<*mut TestObject>>()
1620            == core::mem::size_of::<*mut TestObject>()
1621    );
1622    ::zr::static_assert!(
1623        core::mem::align_of::<DoublyLinkedList<*mut TestObject>>()
1624            == core::mem::align_of::<*mut TestObject>()
1625    );
1626
1627    ::zr::static_assert!(
1628        core::mem::size_of::<DoublyLinkedList<*mut TestObject, DefaultObjectTag, TrackingSize>>()
1629            == 2 * core::mem::size_of::<*mut TestObject>()
1630    );
1631    ::zr::static_assert!(
1632        core::mem::align_of::<DoublyLinkedList<*mut TestObject, DefaultObjectTag, TrackingSize>>()
1633            == core::mem::align_of::<*mut TestObject>()
1634    );
1635
1636    ::zr::static_assert!(
1637        core::mem::size_of::<ForwardIterator<'_, *mut TestObject>>()
1638            == core::mem::size_of::<*mut TestObject>()
1639    );
1640    ::zr::static_assert!(
1641        core::mem::align_of::<ForwardIterator<'_, *mut TestObject>>()
1642            == core::mem::align_of::<*mut TestObject>()
1643    );
1644
1645    ::zr::static_assert!(
1646        core::mem::size_of::<ReverseIterator<'_, *mut TestObject>>()
1647            == core::mem::size_of::<*mut TestObject>()
1648    );
1649    ::zr::static_assert!(
1650        core::mem::align_of::<ReverseIterator<'_, *mut TestObject>>()
1651            == core::mem::align_of::<*mut TestObject>()
1652    );
1653
1654    #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
1655    #[pin_data]
1656    struct UniqueTestObject {
1657        value: i32,
1658        #[pin]
1659        #[dll_node]
1660        node: DoublyLinkedListNode<UniqueTestObject>,
1661    }
1662
1663    impl UniqueTestObject {
1664        fn new(value: i32) -> Self {
1665            Self { value, node: DoublyLinkedListNode::new() }
1666        }
1667    }
1668
1669    impl TestValue for UniqueTestObject {
1670        fn new(value: i32) -> Self {
1671            Self::new(value)
1672        }
1673    }
1674
1675    #[fbl::ref_counted]
1676    #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
1677    #[repr(C)]
1678    pub struct RefTestObject {
1679        value: i32,
1680        #[dll_node]
1681        node: DoublyLinkedListNode<RefTestObject>,
1682    }
1683
1684    impl TestValue for RefTestObject {
1685        fn new_ref_counted(value: i32) -> RefPtr<Self> {
1686            crate::make_ref_counted!(RefTestObject {
1687                value: value,
1688                node: DoublyLinkedListNode::new()
1689            })
1690            .unwrap()
1691        }
1692    }
1693
1694    macro_rules! generate_list_tests {
1695        ($mod_name:ident, $ptr_type:ty, $factory_type:ty, $get_val:expr, $push:expr) => {
1696            mod $mod_name {
1697                use super::*;
1698
1699                #[test]
1700                fn test_basic() {
1701                    let mut factory = <$factory_type>::new();
1702                    stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1703                    assert!(list.is_empty());
1704
1705                    let obj1 = factory.create(1);
1706                    let obj2 = factory.create(2);
1707
1708                    $push(list.as_mut(), obj1);
1709                    $push(list.as_mut(), obj2);
1710
1711                    assert!(!list.is_empty());
1712
1713                    let mut iter = list.iter();
1714                    assert_eq!(iter.next().unwrap().value, 2);
1715                    assert_eq!(iter.next().unwrap().value, 1);
1716                    assert!(iter.next().is_none());
1717
1718                    list.as_mut().clear();
1719                    assert!(list.is_empty());
1720                }
1721
1722                #[test]
1723                fn test_double_ended_iterator() {
1724                    let mut factory = <$factory_type>::new();
1725                    stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1726                    let obj1 = factory.create(1);
1727                    let obj2 = factory.create(2);
1728                    let obj3 = factory.create(3);
1729
1730                    $push(list.as_mut(), obj1);
1731                    $push(list.as_mut(), obj2);
1732                    $push(list.as_mut(), obj3);
1733
1734                    let mut iter = list.iter();
1735                    assert_eq!(iter.next().unwrap().value, 3);
1736                    assert_eq!(iter.next_back().unwrap().value, 1);
1737                    assert_eq!(iter.next().unwrap().value, 2);
1738                    assert!(iter.next().is_none());
1739                    assert!(iter.next_back().is_none());
1740
1741                    list.as_mut().clear();
1742                }
1743
1744                #[test]
1745                fn test_explicit_pops() {
1746                    let mut factory = <$factory_type>::new();
1747                    stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1748                    let obj1 = factory.create(1);
1749                    let obj2 = factory.create(2);
1750
1751                    $push(list.as_mut(), obj1);
1752                    $push(list.as_mut(), obj2);
1753
1754                    let p1 = list.as_mut().pop_front();
1755                    assert!(p1.is_some());
1756                    let p2 = list.as_mut().pop_front();
1757                    assert!(p2.is_some());
1758                    assert!(list.as_mut().pop_front().is_none());
1759                }
1760
1761                #[test]
1762                fn test_cursor_move_prev() {
1763                    let mut factory = <$factory_type>::new();
1764                    stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1765                    let obj1 = factory.create(1);
1766                    let obj2 = factory.create(2);
1767                    let obj3 = factory.create(3);
1768
1769                    $push(list.as_mut(), obj1);
1770                    $push(list.as_mut(), obj2);
1771                    $push(list.as_mut(), obj3);
1772
1773                    let (a, b, c) = {
1774                        let mut iter = list.iter();
1775                        (
1776                            $get_val(iter.next().unwrap()),
1777                            $get_val(iter.next().unwrap()),
1778                            $get_val(iter.next().unwrap()),
1779                        )
1780                    };
1781
1782                    let mut cursor = list.as_mut().cursor_front_mut();
1783                    assert_eq!($get_val(cursor.get().unwrap()), a);
1784
1785                    cursor.move_prev();
1786                    assert!(cursor.get().is_none()); // Sentinel
1787
1788                    cursor.move_prev();
1789                    assert_eq!($get_val(cursor.get().unwrap()), c);
1790
1791                    cursor.move_prev();
1792                    assert_eq!($get_val(cursor.get().unwrap()), b);
1793
1794                    cursor.move_prev();
1795                    assert_eq!($get_val(cursor.get().unwrap()), a);
1796
1797                    list.as_mut().clear();
1798                }
1799
1800                #[test]
1801                fn test_cursor_insert_after() {
1802                    let mut factory = <$factory_type>::new();
1803                    stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1804                    let obj1 = factory.create(1);
1805                    let obj2 = factory.create(2);
1806                    let obj3 = factory.create(3);
1807
1808                    $push(list.as_mut(), obj1);
1809
1810                    let mut cursor = list.as_mut().cursor_front_mut();
1811                    unsafe {
1812                        cursor.insert_after_raw(obj3);
1813                        cursor.insert_after_raw(obj2);
1814                    }
1815
1816                    let mut iter = list.iter();
1817                    assert_eq!($get_val(iter.next().unwrap()), 1);
1818                    assert_eq!($get_val(iter.next().unwrap()), 2);
1819                    assert_eq!($get_val(iter.next().unwrap()), 3);
1820                    assert!(iter.next().is_none());
1821
1822                    list.as_mut().clear();
1823                }
1824
1825                #[test]
1826                fn test_pop_back() {
1827                    let mut factory = <$factory_type>::new();
1828                    stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1829                    let obj1 = factory.create(1);
1830                    let obj2 = factory.create(2);
1831
1832                    $push(list.as_mut(), obj1);
1833                    $push(list.as_mut(), obj2);
1834
1835                    let p1 = list.as_mut().pop_back();
1836                    assert!(p1.is_some());
1837                    let p2 = list.as_mut().pop_back();
1838                    assert!(p2.is_some());
1839                    assert!(list.as_mut().pop_back().is_none());
1840                }
1841
1842                #[test]
1843                fn test_erase() {
1844                    let mut factory = <$factory_type>::new();
1845                    stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1846                    let obj1 = factory.create(1);
1847                    let obj2 = factory.create(2);
1848                    let obj3 = factory.create(3);
1849
1850                    $push(list.as_mut(), obj1);
1851                    $push(list.as_mut(), obj2);
1852                    $push(list.as_mut(), obj3);
1853
1854                    let mut cursor = list.as_mut().cursor_front_mut();
1855                    cursor.move_next();
1856                    let erased = cursor.erase();
1857                    assert!(erased.is_some());
1858                    factory.cleanup(erased.unwrap());
1859
1860                    let mut iter = list.iter();
1861                    assert!(iter.next().is_some());
1862                    assert!(iter.next().is_some());
1863                    assert!(iter.next().is_none());
1864
1865                    list.as_mut().clear();
1866                }
1867
1868                #[test]
1869                fn test_erase_if() {
1870                    let mut factory = <$factory_type>::new();
1871                    stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1872                    let obj1 = factory.create(1);
1873                    let obj2 = factory.create(2);
1874                    let obj3 = factory.create(3);
1875
1876                    $push(list.as_mut(), obj1);
1877                    $push(list.as_mut(), obj2);
1878                    $push(list.as_mut(), obj3);
1879
1880                    let erased = list.as_mut().erase_if(|o| o.value == 2);
1881                    assert!(erased.is_some());
1882                    assert_eq!($get_val(erased.unwrap().get_ref()), 2);
1883
1884                    let mut iter = list.iter();
1885                    assert_eq!($get_val(iter.next().unwrap()), 3);
1886                    assert_eq!($get_val(iter.next().unwrap()), 1);
1887                    assert!(iter.next().is_none());
1888
1889                    list.as_mut().clear();
1890                }
1891
1892                #[test]
1893                fn test_find_if() {
1894                    let mut factory = <$factory_type>::new();
1895                    stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1896                    let obj1 = factory.create(1);
1897                    let obj2 = factory.create(2);
1898
1899                    $push(list.as_mut(), obj1);
1900                    $push(list.as_mut(), obj2);
1901
1902                    let found = list.find_if(|o| o.value == 1);
1903                    assert!(found.is_some());
1904                    assert_eq!(found.unwrap().value, 1);
1905
1906                    let found = list.find_if(|o| o.value == 3);
1907                    assert!(found.is_none());
1908
1909                    list.as_mut().clear();
1910                }
1911
1912                #[test]
1913                fn test_complete_reverse_iteration() {
1914                    let mut factory = <$factory_type>::new();
1915                    stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1916                    let obj1 = factory.create(1);
1917                    let obj2 = factory.create(2);
1918                    let obj3 = factory.create(3);
1919
1920                    $push(list.as_mut(), obj1);
1921                    $push(list.as_mut(), obj2);
1922                    $push(list.as_mut(), obj3);
1923
1924                    let (a, b, c) = {
1925                        let mut iter = list.iter();
1926                        (
1927                            $get_val(iter.next().unwrap()),
1928                            $get_val(iter.next().unwrap()),
1929                            $get_val(iter.next().unwrap()),
1930                        )
1931                    };
1932
1933                    let mut iter = list.iter();
1934                    assert_eq!($get_val(iter.next_back().unwrap()), c);
1935                    assert_eq!($get_val(iter.next_back().unwrap()), b);
1936                    assert_eq!($get_val(iter.next_back().unwrap()), a);
1937                    assert!(iter.next_back().is_none());
1938
1939                    list.as_mut().clear();
1940                }
1941
1942                #[test]
1943                fn test_split_after() {
1944                    let mut factory = <$factory_type>::new();
1945                    stack_pin_init!(let list1 = DoublyLinkedList::<$ptr_type>::new());
1946                    stack_pin_init!(let list2 = DoublyLinkedList::<$ptr_type>::new());
1947
1948                    let obj1 = factory.create(1);
1949                    let obj2 = factory.create(2);
1950                    let obj3 = factory.create(3);
1951                    let obj4 = factory.create(4);
1952
1953                    $push(list1.as_mut(), obj4);
1954                    $push(list1.as_mut(), obj3);
1955                    $push(list1.as_mut(), obj2);
1956                    $push(list1.as_mut(), obj1);
1957
1958                    let mut cursor = list1.as_mut().cursor_front_mut();
1959                    cursor.move_next(); // points to 2
1960
1961                    let mut dest_cursor = list2.as_mut().cursor_back_mut();
1962                    cursor.split_after(&mut dest_cursor);
1963
1964                    let mut iter1 = list1.iter();
1965                    assert_eq!($get_val(iter1.next().unwrap()), 1);
1966                    assert_eq!($get_val(iter1.next().unwrap()), 2);
1967                    assert!(iter1.next().is_none());
1968
1969                    let mut iter2 = list2.iter();
1970                    assert_eq!($get_val(iter2.next().unwrap()), 3);
1971                    assert_eq!($get_val(iter2.next().unwrap()), 4);
1972                    assert!(iter2.next().is_none());
1973
1974                    list1.as_mut().clear();
1975                    list2.as_mut().clear();
1976                }
1977
1978                #[test]
1979                fn test_split_before() {
1980                    let mut factory = <$factory_type>::new();
1981                    stack_pin_init!(let list1 = DoublyLinkedList::<$ptr_type>::new());
1982                    stack_pin_init!(let list2 = DoublyLinkedList::<$ptr_type>::new());
1983
1984                    let obj1 = factory.create(1);
1985                    let obj2 = factory.create(2);
1986                    let obj3 = factory.create(3);
1987                    let obj4 = factory.create(4);
1988
1989                    $push(list1.as_mut(), obj4);
1990                    $push(list1.as_mut(), obj3);
1991                    $push(list1.as_mut(), obj2);
1992                    $push(list1.as_mut(), obj1);
1993
1994                    let mut cursor = list1.as_mut().cursor_front_mut();
1995                    cursor.move_next();
1996                    cursor.move_next(); // points to 3
1997
1998                    let mut dest_cursor = list2.as_mut().cursor_back_mut();
1999                    cursor.split_before(&mut dest_cursor);
2000
2001                    // list2 should have elements before cursor (1, 2)
2002                    let mut iter2 = list2.iter();
2003                    assert_eq!($get_val(iter2.next().unwrap()), 1);
2004                    assert_eq!($get_val(iter2.next().unwrap()), 2);
2005                    assert!(iter2.next().is_none());
2006
2007                    // list1 should have elements from cursor onwards (3, 4)
2008                    let mut iter1 = list1.iter();
2009                    assert_eq!($get_val(iter1.next().unwrap()), 3);
2010                    assert_eq!($get_val(iter1.next().unwrap()), 4);
2011                    assert!(iter1.next().is_none());
2012
2013                    list1.as_mut().clear();
2014                    list2.as_mut().clear();
2015                }
2016            }
2017        };
2018    }
2019
2020    generate_list_tests!(
2021        raw_ptr_tests,
2022        *mut TestObject,
2023        RawFactory<TestObject>,
2024        |p: &TestObject| p.value,
2025        |list: Pin<&mut DoublyLinkedList<*mut TestObject>>, obj| {
2026            // SAFETY: `obj` is a freshly allocated, unlinked object that outlives the list.
2027            unsafe { list.push_front_raw(obj) };
2028        }
2029    );
2030
2031    generate_list_tests!(
2032        unique_ptr_tests,
2033        UniquePtr<UniqueTestObject>,
2034        UniqueFactory<UniqueTestObject>,
2035        |p: &UniqueTestObject| p.value,
2036        |list: Pin<&mut DoublyLinkedList<UniquePtr<UniqueTestObject>>>, obj| list.push_front(obj)
2037    );
2038
2039    generate_list_tests!(
2040        ref_ptr_tests,
2041        RefPtr<RefTestObject>,
2042        RefFactory<RefTestObject>,
2043        |p: &RefTestObject| p.value,
2044        |list: Pin<&mut DoublyLinkedList<RefPtr<RefTestObject>>>, obj| list.push_front(obj)
2045    );
2046
2047    #[test]
2048    fn test_tracking_size() {
2049        stack_pin_init!(let list =
2050            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2051
2052        assert_eq!(list.len(), 0);
2053        list.as_mut().push_front(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2054        assert_eq!(list.len(), 1);
2055        list.as_mut().push_front(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2056        assert_eq!(list.len(), 2);
2057        list.as_mut().pop_front();
2058        assert_eq!(list.len(), 1);
2059        list.as_mut().clear();
2060        assert_eq!(list.len(), 0);
2061    }
2062
2063    #[test]
2064    fn test_insert_before() {
2065        stack_pin_init!(let list =
2066            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2067
2068        let mut cursor = list.as_mut().cursor_front_mut();
2069        cursor.insert_before(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2070        assert_eq!(list.len(), 1);
2071        assert_eq!(list.front().unwrap().value, 1);
2072
2073        let mut cursor = list.as_mut().cursor_front_mut();
2074        cursor.insert_before(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2075        assert_eq!(list.len(), 2);
2076        assert_eq!(list.front().unwrap().value, 2);
2077
2078        let mut cursor = list.as_mut().cursor_front_mut();
2079        cursor.move_next(); // point to obj1
2080        cursor.insert_before(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2081        assert_eq!(list.len(), 3);
2082
2083        let mut cursor = list.as_mut().cursor_front_mut();
2084        while cursor.get().unwrap().value != 1 {
2085            cursor.move_next();
2086        }
2087        cursor.move_next(); // point to sentinel
2088        cursor.insert_before(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
2089        assert_eq!(list.len(), 4);
2090
2091        let mut iter = list.iter();
2092        assert_eq!(iter.next().unwrap().value, 2);
2093        assert_eq!(iter.next().unwrap().value, 3);
2094        assert_eq!(iter.next().unwrap().value, 1);
2095        assert_eq!(iter.next().unwrap().value, 4);
2096        assert!(iter.next().is_none());
2097
2098        list.as_mut().clear();
2099    }
2100
2101    #[test]
2102    fn test_front_mut_and_back_mut() {
2103        stack_pin_init!(let list =
2104            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2105
2106        assert!(list.as_mut().front_mut().is_none());
2107        assert!(list.as_mut().back_mut().is_none());
2108
2109        // 1-element list: head == tail.
2110        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2111        *list.as_mut().front_mut().unwrap().project().value = 2;
2112        assert_eq!(list.as_mut().back_mut().unwrap().value, 2);
2113        *list.as_mut().back_mut().unwrap().project().value = 3;
2114        assert_eq!(list.as_mut().front_mut().unwrap().value, 3);
2115        assert_eq!(list.front().unwrap().value, 3);
2116        assert_eq!(list.back().unwrap().value, 3);
2117        assert_eq!(list.as_mut().pop_front().unwrap().value, 3);
2118        assert!(list.is_empty());
2119
2120        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(10)).unwrap());
2121        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(20)).unwrap());
2122
2123        assert_eq!(list.as_mut().front_mut().unwrap().value, 10);
2124        assert_eq!(list.as_mut().back_mut().unwrap().value, 20);
2125
2126        *list.as_mut().front_mut().unwrap().project().value = 100;
2127        *list.as_mut().back_mut().unwrap().project().value = 200;
2128
2129        assert_eq!(list.front().unwrap().value, 100);
2130        assert_eq!(list.back().unwrap().value, 200);
2131
2132        list.as_mut().clear();
2133    }
2134
2135    // Compile-time check that `T` does NOT implement `Trait`. If `T` implemented `Trait`, the
2136    // `<T as AmbiguousIfImpl<_>>` path below would be ambiguous between the two impls and fail to
2137    // compile.
2138    macro_rules! assert_not_impl {
2139        ($t:ty: $($trait:tt)+) => {
2140            const _: fn() = || {
2141                trait AmbiguousIfImpl<A> {
2142                    fn some_item() {}
2143                }
2144                impl<T: ?Sized> AmbiguousIfImpl<()> for T {}
2145                enum Invalid {}
2146                impl<T: ?Sized + $($trait)+> AmbiguousIfImpl<Invalid> for T {}
2147                let _ = <$t as AmbiguousIfImpl<_>>::some_item;
2148            };
2149        };
2150    }
2151
2152    // Linked elements must not be movable through safe `Pin` APIs.
2153    assert_not_impl!(DoublyLinkedListNode<TestObject>: Unpin);
2154    assert_not_impl!(TestObject: Unpin);
2155    assert_not_impl!(UniqueTestObject: Unpin);
2156    assert_not_impl!(RefTestObject: Unpin);
2157    // Lists must not be movable through safe `Pin` APIs, since elements point back at them.
2158    assert_not_impl!(DoublyLinkedList<*mut TestObject>: Unpin);
2159    // Shared ownership must not grant mutable element access.
2160    assert_not_impl!(RefPtr<RefTestObject>: MutPtr);
2161
2162    #[test]
2163    fn test_iter_mut() {
2164        stack_pin_init!(let list =
2165            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2166
2167        assert!(list.as_mut().iter_mut().next().is_none());
2168        assert!(list.as_mut().iter_mut().next_back().is_none());
2169
2170        // 1-element list: head == tail and head.prev == head.
2171        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(7)).unwrap());
2172        {
2173            let mut iter = list.as_mut().iter_mut();
2174            let only = iter.next_back().unwrap();
2175            assert_eq!(only.value, 7);
2176            *only.project().value = 8;
2177            assert!(iter.next_back().is_none());
2178            assert!(iter.next().is_none());
2179        }
2180        {
2181            let mut iter = list.as_mut().iter_mut();
2182            assert_eq!(iter.next().unwrap().value, 8);
2183            assert!(iter.next().is_none());
2184            assert!(iter.next_back().is_none());
2185        }
2186        assert_eq!(list.as_mut().pop_front().unwrap().value, 8);
2187        assert!(list.is_empty());
2188
2189        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2190        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2191        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2192
2193        for obj in list.as_mut().iter_mut() {
2194            *obj.project().value *= 10;
2195        }
2196
2197        let mut iter = list.as_mut().iter_mut();
2198        assert_eq!(iter.next().unwrap().value, 10);
2199        let mut last = iter.next_back().unwrap();
2200        assert_eq!(last.value, 30);
2201        *last.as_mut().project().value += 1;
2202        let mut middle = iter.next().unwrap();
2203        *middle.as_mut().project().value += 2;
2204        assert!(iter.next().is_none());
2205        assert!(iter.next_back().is_none());
2206
2207        let values: alloc::vec::Vec<i32> = list.iter().map(|o| o.value).collect();
2208        assert_eq!(values, [10, 22, 31]);
2209        assert_eq!(list.len(), 3);
2210
2211        // Hold every yielded reference simultaneously.
2212        {
2213            let mut items: alloc::vec::Vec<_> = list.as_mut().iter_mut().collect();
2214            assert_eq!(items.len(), 3);
2215            for item in items.iter_mut() {
2216                *item.as_mut().project().value += 1;
2217            }
2218            *items[0].as_mut().project().value += 100;
2219            *items[2].as_mut().project().value += 200;
2220        }
2221        let values: alloc::vec::Vec<i32> = list.iter().map(|o| o.value).collect();
2222        assert_eq!(values, [111, 23, 232]);
2223
2224        list.as_mut().clear();
2225        assert!(list.is_empty());
2226
2227        // 2-element list: hold `first` (the head) across the `next_back()` call where the front
2228        // and back iterators meet, and write to it afterward.
2229        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2230        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2231        {
2232            let mut iter = list.as_mut().iter_mut();
2233            let mut first = iter.next().unwrap();
2234            *first.as_mut().project().value = 10;
2235            let mut second = iter.next_back().unwrap();
2236            *first.as_mut().project().value = 11;
2237            *second.as_mut().project().value = 20;
2238            assert!(iter.next().is_none());
2239            assert!(iter.next_back().is_none());
2240            assert_eq!(first.value, 11);
2241            assert_eq!(second.value, 20);
2242        }
2243        let values: alloc::vec::Vec<i32> = list.iter().map(|o| o.value).collect();
2244        assert_eq!(values, [11, 20]);
2245
2246        // Same as above, but starting from the back.
2247        {
2248            let mut iter = list.as_mut().iter_mut();
2249            let mut last = iter.next_back().unwrap();
2250            *last.as_mut().project().value = 21;
2251            let mut first = iter.next().unwrap();
2252            *last.as_mut().project().value = 22;
2253            *first.as_mut().project().value = 12;
2254            assert!(iter.next().is_none());
2255            assert!(iter.next_back().is_none());
2256        }
2257        let values: alloc::vec::Vec<i32> = list.iter().map(|o| o.value).collect();
2258        assert_eq!(values, [12, 22]);
2259
2260        list.as_mut().clear();
2261    }
2262
2263    #[test]
2264    fn test_forward_and_reverse_iter_mut() {
2265        stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<UniqueTestObject>>::new());
2266
2267        assert!(list.as_mut().forward_iter_mut().next().is_none());
2268        assert!(list.as_mut().reverse_iter_mut().next().is_none());
2269
2270        // 1-element list: head == tail and head.prev == head.
2271        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(5)).unwrap());
2272        {
2273            let mut r_iter = list.as_mut().reverse_iter_mut();
2274            let only = r_iter.next().unwrap();
2275            assert_eq!(only.value, 5);
2276            *only.project().value = 6;
2277            assert!(r_iter.next().is_none());
2278        }
2279        {
2280            let mut f_iter = list.as_mut().forward_iter_mut();
2281            assert_eq!(f_iter.next().unwrap().value, 6);
2282            assert!(f_iter.next().is_none());
2283        }
2284        assert_eq!(list.as_mut().pop_front().unwrap().value, 6);
2285        assert!(list.is_empty());
2286
2287        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2288        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2289        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2290
2291        // Forward: add 10 to every element.
2292        for obj in list.as_mut().forward_iter_mut() {
2293            *obj.project().value += 10;
2294        }
2295        let values: alloc::vec::Vec<i32> = list.iter().map(|o| o.value).collect();
2296        assert_eq!(values, [11, 12, 13]);
2297
2298        // Reverse: visit in reverse order and record it.
2299        let mut visited = alloc::vec::Vec::new();
2300        for obj in list.as_mut().reverse_iter_mut() {
2301            visited.push(obj.value);
2302            *obj.project().value *= 2;
2303        }
2304        assert_eq!(visited, [13, 12, 11]);
2305        let values: alloc::vec::Vec<i32> = list.iter().map(|o| o.value).collect();
2306        assert_eq!(values, [22, 24, 26]);
2307
2308        // Hold every yielded reference from the reverse iterator simultaneously.
2309        {
2310            let mut items: alloc::vec::Vec<_> = list.as_mut().reverse_iter_mut().collect();
2311            assert_eq!(items.len(), 3);
2312            for item in items.iter_mut() {
2313                *item.as_mut().project().value += 1;
2314            }
2315            // `items[0]` is the tail and `items[2]` is the head; write to both after all
2316            // references were yielded.
2317            *items[0].as_mut().project().value += 100;
2318            *items[2].as_mut().project().value += 200;
2319            assert_eq!(items[0].value, 127);
2320            assert_eq!(items[1].value, 25);
2321            assert_eq!(items[2].value, 223);
2322        }
2323        let values: alloc::vec::Vec<i32> = list.iter().map(|o| o.value).collect();
2324        assert_eq!(values, [223, 25, 127]);
2325
2326        // Hold every yielded reference from the forward iterator simultaneously.
2327        {
2328            let mut items: alloc::vec::Vec<_> = list.as_mut().forward_iter_mut().collect();
2329            assert_eq!(items.len(), 3);
2330            for item in items.iter_mut() {
2331                *item.as_mut().project().value -= 1;
2332            }
2333            *items[2].as_mut().project().value -= 100;
2334            *items[0].as_mut().project().value -= 200;
2335        }
2336        let values: alloc::vec::Vec<i32> = list.iter().map(|o| o.value).collect();
2337        assert_eq!(values, [22, 24, 26]);
2338
2339        list.as_mut().clear();
2340    }
2341
2342    #[test]
2343    fn test_iter_mut_raw_ptr() {
2344        stack_pin_init!(let list = DoublyLinkedList::<*mut TestObject>::new());
2345        let mut obj1 = TestObject::new(1);
2346        let mut obj2 = TestObject::new(2);
2347
2348        // SAFETY: The objects outlive the list and are removed before the list is dropped.
2349        unsafe {
2350            list.as_mut().push_back_raw(&mut obj1);
2351            list.as_mut().push_back_raw(&mut obj2);
2352        }
2353
2354        for obj in list.as_mut().iter_mut() {
2355            *obj.project().value += 100;
2356        }
2357        *list.as_mut().front_mut().unwrap().project().value += 1;
2358        *list.as_mut().back_mut().unwrap().project().value += 2;
2359
2360        let values: alloc::vec::Vec<i32> = list.iter().map(|o| o.value).collect();
2361        assert_eq!(values, [102, 104]);
2362
2363        list.as_mut().clear();
2364    }
2365
2366    #[test]
2367    fn test_cursor_get_mut() {
2368        stack_pin_init!(let list =
2369            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2370
2371        assert!(list.as_mut().cursor_front_mut().get_mut().is_none());
2372
2373        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2374        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2375
2376        let mut cursor = list.as_mut().cursor_front_mut();
2377        *cursor.get_mut().unwrap().project().value = 10;
2378        cursor.move_next();
2379        assert_eq!(cursor.get_mut().unwrap().value, 2);
2380        *cursor.get_mut().unwrap().project().value = 20;
2381        cursor.move_next();
2382        assert!(cursor.get_mut().is_none()); // Sentinel.
2383
2384        let mut iter = list.iter();
2385        assert_eq!(iter.next().unwrap().value, 10);
2386        assert_eq!(iter.next().unwrap().value, 20);
2387        assert!(iter.next().is_none());
2388        assert_eq!(list.len(), 2);
2389
2390        list.as_mut().clear();
2391    }
2392
2393    #[test]
2394    fn test_cursor_front_and_back_mut() {
2395        stack_pin_init!(let list =
2396            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2397
2398        assert!(list.as_mut().cursor_front_mut().get().is_none());
2399        assert!(list.as_mut().cursor_back_mut().get().is_none());
2400
2401        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(10)).unwrap());
2402        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(20)).unwrap());
2403
2404        let mut front_cursor = list.as_mut().cursor_front_mut();
2405        assert_eq!(front_cursor.get().unwrap().value, 10);
2406        front_cursor.move_next();
2407        assert_eq!(front_cursor.get().unwrap().value, 20);
2408
2409        let mut back_cursor = list.as_mut().cursor_back_mut();
2410        assert!(back_cursor.get().is_none());
2411        back_cursor.move_prev();
2412        assert_eq!(back_cursor.get().unwrap().value, 20);
2413
2414        let mut back_cursor = list.as_mut().cursor_back_mut();
2415        back_cursor.insert_before(UniquePtr::try_new(UniqueTestObject::new(30)).unwrap());
2416        assert_eq!(list.len(), 3);
2417        assert_eq!(list.back().unwrap().value, 30);
2418
2419        list.as_mut().clear();
2420    }
2421
2422    #[test]
2423    fn test_splice_middle() {
2424        stack_pin_init!(let list1 =
2425            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2426        stack_pin_init!(let list2 =
2427            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2428
2429        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2430        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2431        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2432        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
2433
2434        let mut cursor = list1.as_mut().cursor_front_mut();
2435        cursor.move_next(); // point to obj2
2436
2437        cursor.splice(list2.as_mut());
2438
2439        assert!(list2.is_empty());
2440        assert_eq!(list1.len(), 4);
2441
2442        let mut iter = list1.iter();
2443        assert_eq!(iter.next().unwrap().value, 1);
2444        assert_eq!(iter.next().unwrap().value, 3);
2445        assert_eq!(iter.next().unwrap().value, 4);
2446        assert_eq!(iter.next().unwrap().value, 2);
2447        assert!(iter.next().is_none());
2448
2449        list1.as_mut().clear();
2450    }
2451
2452    #[test]
2453    fn test_splice_head() {
2454        stack_pin_init!(let list1 =
2455            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2456        stack_pin_init!(let list2 =
2457            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2458
2459        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2460        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2461        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2462        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
2463
2464        let mut cursor = list1.as_mut().cursor_front_mut();
2465
2466        cursor.splice(list2.as_mut());
2467
2468        assert!(list2.is_empty());
2469        assert_eq!(list1.len(), 4);
2470
2471        let mut iter = list1.iter();
2472        assert_eq!(iter.next().unwrap().value, 3);
2473        assert_eq!(iter.next().unwrap().value, 4);
2474        assert_eq!(iter.next().unwrap().value, 1);
2475        assert_eq!(iter.next().unwrap().value, 2);
2476        assert!(iter.next().is_none());
2477
2478        list1.as_mut().clear();
2479    }
2480
2481    #[test]
2482    fn test_splice_tail() {
2483        stack_pin_init!(let list1 =
2484            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2485        stack_pin_init!(let list2 =
2486            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2487
2488        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2489        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2490        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2491        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
2492
2493        let mut cursor = list1.as_mut().cursor_front_mut();
2494        cursor.move_next();
2495        cursor.move_next(); // point to sentinel
2496
2497        cursor.splice(list2.as_mut());
2498
2499        assert!(list2.is_empty());
2500        assert_eq!(list1.len(), 4);
2501
2502        let mut iter = list1.iter();
2503        assert_eq!(iter.next().unwrap().value, 1);
2504        assert_eq!(iter.next().unwrap().value, 2);
2505        assert_eq!(iter.next().unwrap().value, 3);
2506        assert_eq!(iter.next().unwrap().value, 4);
2507        assert!(iter.next().is_none());
2508
2509        list1.as_mut().clear();
2510    }
2511
2512    #[test]
2513    fn test_splice_empty() {
2514        stack_pin_init!(let list1 =
2515            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2516        stack_pin_init!(let list2 =
2517            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2518
2519        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2520        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2521
2522        let mut cursor = list1.as_mut().cursor_front_mut();
2523        cursor.splice(list2.as_mut());
2524
2525        assert!(list2.is_empty());
2526        assert_eq!(list1.len(), 2);
2527
2528        let mut iter = list1.iter();
2529        assert_eq!(iter.next().unwrap().value, 1);
2530        assert_eq!(iter.next().unwrap().value, 2);
2531        assert!(iter.next().is_none());
2532
2533        list1.as_mut().clear();
2534    }
2535
2536    #[test]
2537    fn test_splice_non_tracking() {
2538        stack_pin_init!(let list1 =
2539            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, NonTrackingSize>::new());
2540        stack_pin_init!(let list2 =
2541            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, NonTrackingSize>::new());
2542
2543        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2544        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2545        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2546        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
2547
2548        let mut cursor = list1.as_mut().cursor_front_mut();
2549        cursor.move_next(); // point to obj2
2550
2551        cursor.splice(list2.as_mut());
2552
2553        assert!(list2.is_empty());
2554
2555        let mut iter = list1.iter();
2556        assert_eq!(iter.next().unwrap().value, 1);
2557        assert_eq!(iter.next().unwrap().value, 3);
2558        assert_eq!(iter.next().unwrap().value, 4);
2559        assert_eq!(iter.next().unwrap().value, 2);
2560        assert!(iter.next().is_none());
2561
2562        list1.as_mut().clear();
2563    }
2564
2565    #[test]
2566    fn test_list_splice() {
2567        // Test splicing non-empty other into non-empty self.
2568        stack_pin_init!(let list1 =
2569            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2570        stack_pin_init!(let list2 =
2571            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2572
2573        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2574        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2575        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2576        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
2577
2578        list1.as_mut().splice(list2.as_mut());
2579
2580        assert!(list2.is_empty());
2581        assert_eq!(list2.len(), 0);
2582        assert_eq!(list1.len(), 4);
2583
2584        let mut iter = list1.iter();
2585        assert_eq!(iter.next().unwrap().value, 1);
2586        assert_eq!(iter.next().unwrap().value, 2);
2587        assert_eq!(iter.next().unwrap().value, 3);
2588        assert_eq!(iter.next().unwrap().value, 4);
2589        assert!(iter.next().is_none());
2590
2591        // Test splicing into empty self.
2592        stack_pin_init!(let list3 =
2593            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2594
2595        list3.as_mut().splice(list1.as_mut());
2596
2597        assert!(list1.is_empty());
2598        assert_eq!(list1.len(), 0);
2599        assert_eq!(list3.len(), 4);
2600
2601        let mut iter = list3.iter();
2602        assert_eq!(iter.next().unwrap().value, 1);
2603        assert_eq!(iter.next().unwrap().value, 2);
2604        assert_eq!(iter.next().unwrap().value, 3);
2605        assert_eq!(iter.next().unwrap().value, 4);
2606        assert!(iter.next().is_none());
2607
2608        // Test splicing empty list into non-empty self (no-op).
2609        list3.as_mut().splice(list1.as_mut());
2610        assert_eq!(list3.len(), 4);
2611        assert!(list1.is_empty());
2612
2613        list3.as_mut().clear();
2614    }
2615
2616    #[test]
2617    fn test_split_after_at_tail() {
2618        stack_pin_init!(let list1 =
2619            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2620        stack_pin_init!(let list2 =
2621            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2622
2623        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2624        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2625
2626        let mut cursor = list1.as_mut().cursor_front_mut();
2627        cursor.move_next(); // points to 2 (tail)
2628
2629        let mut dest_cursor = list2.as_mut().cursor_back_mut();
2630        cursor.split_after(&mut dest_cursor);
2631
2632        assert!(list2.is_empty());
2633        assert_eq!(list2.len(), 0);
2634        assert_eq!(list1.len(), 2);
2635
2636        list1.as_mut().clear();
2637    }
2638
2639    #[test]
2640    fn test_split_after_at_head() {
2641        stack_pin_init!(let list1 =
2642            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2643        stack_pin_init!(let list2 =
2644            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2645
2646        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2647        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2648        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2649
2650        let mut cursor = list1.as_mut().cursor_front_mut(); // points to 1 (head)
2651
2652        let mut dest_cursor = list2.as_mut().cursor_back_mut();
2653        cursor.split_after(&mut dest_cursor);
2654
2655        assert_eq!(list1.len(), 1);
2656        assert_eq!(list2.len(), 2);
2657
2658        let mut iter1 = list1.iter();
2659        assert_eq!(iter1.next().unwrap().value, 1);
2660        assert!(iter1.next().is_none());
2661
2662        let mut iter2 = list2.iter();
2663        assert_eq!(iter2.next().unwrap().value, 2);
2664        assert_eq!(iter2.next().unwrap().value, 3);
2665        assert!(iter2.next().is_none());
2666
2667        list1.as_mut().clear();
2668        list2.as_mut().clear();
2669    }
2670
2671    #[test]
2672    fn test_split_before_at_head() {
2673        stack_pin_init!(let list1 =
2674            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2675        stack_pin_init!(let list2 =
2676            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2677
2678        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2679        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2680
2681        let mut cursor = list1.as_mut().cursor_front_mut(); // points to 1 (head)
2682
2683        let mut dest_cursor = list2.as_mut().cursor_back_mut();
2684        cursor.split_before(&mut dest_cursor);
2685
2686        assert!(list2.is_empty());
2687        assert_eq!(list2.len(), 0);
2688        assert_eq!(list1.len(), 2);
2689
2690        list1.as_mut().clear();
2691    }
2692
2693    #[test]
2694    fn test_split_before_at_tail() {
2695        stack_pin_init!(let list1 =
2696            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2697        stack_pin_init!(let list2 =
2698            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2699
2700        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2701        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2702        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2703
2704        let mut cursor = list1.as_mut().cursor_front_mut();
2705        cursor.move_next();
2706        cursor.move_next(); // points to 3 (tail)
2707
2708        let mut dest_cursor = list2.as_mut().cursor_back_mut();
2709        cursor.split_before(&mut dest_cursor);
2710
2711        assert_eq!(list2.len(), 2);
2712        assert_eq!(list1.len(), 1);
2713
2714        let mut iter2 = list2.iter();
2715        assert_eq!(iter2.next().unwrap().value, 1);
2716        assert_eq!(iter2.next().unwrap().value, 2);
2717        assert!(iter2.next().is_none());
2718
2719        let mut iter1 = list1.iter();
2720        assert_eq!(iter1.next().unwrap().value, 3);
2721        assert!(iter1.next().is_none());
2722
2723        list1.as_mut().clear();
2724        list2.as_mut().clear();
2725    }
2726
2727    #[test]
2728    fn test_split_before_at_sentinel() {
2729        stack_pin_init!(let list1 =
2730            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2731        stack_pin_init!(let list2 =
2732            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2733
2734        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2735        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2736
2737        let mut cursor = list1.as_mut().cursor_back_mut(); // points to sentinel
2738
2739        let mut dest_cursor = list2.as_mut().cursor_back_mut();
2740        cursor.split_before(&mut dest_cursor);
2741
2742        assert!(list1.is_empty());
2743        assert_eq!(list1.len(), 0);
2744        assert_eq!(list2.len(), 2);
2745
2746        let mut iter2 = list2.iter();
2747        assert_eq!(iter2.next().unwrap().value, 1);
2748        assert_eq!(iter2.next().unwrap().value, 2);
2749        assert!(iter2.next().is_none());
2750
2751        list2.as_mut().clear();
2752    }
2753
2754    #[test]
2755    fn test_split_into_middle_of_dest_list() {
2756        stack_pin_init!(let list1 =
2757            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2758        stack_pin_init!(let list2 =
2759            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2760
2761        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2762        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2763        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2764        list1.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
2765
2766        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(10)).unwrap());
2767        list2.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(20)).unwrap());
2768
2769        // Split after 2 from list1, and insert before 20 in list2
2770        let mut cursor1 = list1.as_mut().cursor_front_mut();
2771        cursor1.move_next(); // points to 2
2772
2773        let mut cursor2 = list2.as_mut().cursor_front_mut();
2774        cursor2.move_next(); // points to 20
2775
2776        cursor1.split_after(&mut cursor2);
2777
2778        // list1 should retain [1, 2]
2779        assert_eq!(list1.len(), 2);
2780        let mut iter1 = list1.iter();
2781        assert_eq!(iter1.next().unwrap().value, 1);
2782        assert_eq!(iter1.next().unwrap().value, 2);
2783        assert!(iter1.next().is_none());
2784
2785        // list2 should now be [10, 3, 4, 20]
2786        assert_eq!(list2.len(), 4);
2787        let mut iter2 = list2.iter();
2788        assert_eq!(iter2.next().unwrap().value, 10);
2789        assert_eq!(iter2.next().unwrap().value, 3);
2790        assert_eq!(iter2.next().unwrap().value, 4);
2791        assert_eq!(iter2.next().unwrap().value, 20);
2792        assert!(iter2.next().is_none());
2793
2794        list1.as_mut().clear();
2795        list2.as_mut().clear();
2796    }
2797
2798    #[test]
2799    fn test_list_split_methods() {
2800        let mut obj1 = TestObject::new(1);
2801        let mut obj2 = TestObject::new(2);
2802        let mut obj3 = TestObject::new(3);
2803
2804        stack_pin_init!(let list1 = DoublyLinkedList::<*mut TestObject>::new());
2805        stack_pin_init!(let list2 = DoublyLinkedList::<*mut TestObject>::new());
2806
2807        unsafe {
2808            list1.as_mut().push_back_raw(&mut obj1);
2809            list1.as_mut().push_back_raw(&mut obj2);
2810            list1.as_mut().push_back_raw(&mut obj3);
2811
2812            // Split after obj1
2813            let mut cursor1 = list1.as_mut().cursor_at(&obj1);
2814            let mut cursor2 = list2.as_mut().cursor_back_mut();
2815            cursor1.split_after(&mut cursor2);
2816
2817            assert_eq!(list1.iter().count(), 1);
2818            assert_eq!(list2.iter().count(), 2);
2819
2820            let mut iter1 = list1.iter();
2821            assert_eq!(iter1.next().unwrap().value, 1);
2822            assert!(iter1.next().is_none());
2823
2824            let mut iter2 = list2.iter();
2825            assert_eq!(iter2.next().unwrap().value, 2);
2826            assert_eq!(iter2.next().unwrap().value, 3);
2827            assert!(iter2.next().is_none());
2828
2829            // Splice back
2830            list1.as_mut().splice(list2.as_mut());
2831            assert_eq!(list1.iter().count(), 3);
2832
2833            // Split before obj3
2834            let mut cursor1 = list1.as_mut().cursor_at(&obj3);
2835            let mut cursor2 = list2.as_mut().cursor_back_mut();
2836            cursor1.split_before(&mut cursor2);
2837
2838            assert_eq!(list2.iter().count(), 2);
2839            assert_eq!(list1.iter().count(), 1);
2840
2841            let mut iter2 = list2.iter();
2842            assert_eq!(iter2.next().unwrap().value, 1);
2843            assert_eq!(iter2.next().unwrap().value, 2);
2844            assert!(iter2.next().is_none());
2845
2846            let mut iter1 = list1.iter();
2847            assert_eq!(iter1.next().unwrap().value, 3);
2848            assert!(iter1.next().is_none());
2849
2850            list1.as_mut().clear();
2851            list2.as_mut().clear();
2852        }
2853    }
2854
2855    #[test]
2856    fn test_cursor_get() {
2857        stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<UniqueTestObject>>::new());
2858
2859        let cursor = list.as_mut().cursor_front_mut();
2860        assert!(cursor.get().is_none());
2861
2862        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(42)).unwrap());
2863
2864        let mut cursor = list.as_mut().cursor_front_mut();
2865        assert!(cursor.get().is_some());
2866        assert_eq!(cursor.get().unwrap().value, 42);
2867
2868        cursor.move_next();
2869        assert!(cursor.get().is_none());
2870
2871        list.as_mut().clear();
2872    }
2873
2874    #[test]
2875    fn test_pop_back() {
2876        stack_pin_init!(let list =
2877            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2878
2879        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2880        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2881
2882        assert_eq!(list.len(), 2);
2883        let popped = list.as_mut().pop_back();
2884        assert!(popped.is_some());
2885        assert_eq!(popped.unwrap().value, 2);
2886        assert_eq!(list.len(), 1);
2887
2888        let popped = list.as_mut().pop_back();
2889        assert!(popped.is_some());
2890        assert_eq!(popped.unwrap().value, 1);
2891        assert_eq!(list.len(), 0);
2892
2893        assert!(list.as_mut().pop_back().is_none());
2894    }
2895
2896    #[test]
2897    fn test_erase() {
2898        stack_pin_init!(let list =
2899            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2900
2901        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2902        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2903        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2904
2905        assert_eq!(list.len(), 3);
2906
2907        // 1. Erase middle (obj2)
2908        let mut cursor = list.as_mut().cursor_front_mut();
2909        cursor.move_next(); // point to obj2
2910        let erased = cursor.erase();
2911        assert!(erased.is_some());
2912        assert_eq!(erased.unwrap().value, 2);
2913        assert_eq!(list.len(), 2);
2914
2915        let mut iter = list.iter();
2916        assert_eq!(iter.next().unwrap().value, 1);
2917        assert_eq!(iter.next().unwrap().value, 3);
2918        assert!(iter.next().is_none());
2919
2920        // 2. Erase head (obj1)
2921        let mut cursor = list.as_mut().cursor_front_mut();
2922        let erased = cursor.erase(); // current is head (obj1)
2923        assert!(erased.is_some());
2924        assert_eq!(erased.unwrap().value, 1);
2925        assert_eq!(list.len(), 1);
2926        assert_eq!(list.front().unwrap().value, 3); // obj3 is now head!
2927
2928        // 3. Erase last element (obj3)
2929        let mut cursor = list.as_mut().cursor_front_mut();
2930        let erased = cursor.erase(); // current is head/tail (obj3)
2931        assert!(erased.is_some());
2932        assert_eq!(erased.unwrap().value, 3);
2933        assert_eq!(list.len(), 0);
2934        assert!(list.is_empty());
2935
2936        list.as_mut().clear();
2937    }
2938
2939    #[test]
2940    fn test_erase_if() {
2941        stack_pin_init!(let list =
2942            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2943
2944        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2945        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2946        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2947
2948        let erased = list.as_mut().erase_if(|obj| obj.value % 2 == 0);
2949        assert!(erased.is_some());
2950        assert_eq!(erased.unwrap().value, 2);
2951
2952        assert_eq!(list.len(), 2);
2953        let mut iter = list.iter();
2954        assert_eq!(iter.next().unwrap().value, 1);
2955        assert_eq!(iter.next().unwrap().value, 3);
2956        assert!(iter.next().is_none());
2957
2958        list.as_mut().clear();
2959    }
2960
2961    #[test]
2962    fn test_erase_by_reference() {
2963        stack_pin_init!(let list =
2964            DoublyLinkedList::<*mut TestObject, DefaultObjectTag, TrackingSize>::new());
2965        let mut obj1 = TestObject::new(1);
2966        let mut obj2 = TestObject::new(2);
2967        let mut obj3 = TestObject::new(3);
2968
2969        unsafe {
2970            list.as_mut().push_back_raw(&mut obj1);
2971            list.as_mut().push_back_raw(&mut obj2);
2972            list.as_mut().push_back_raw(&mut obj3);
2973        }
2974
2975        assert_eq!(list.len(), 3);
2976
2977        // Erase obj2 directly (safe because it's unmanaged raw pointer to stack)
2978        let erased = unsafe { list.as_mut().erase(&obj2) };
2979        assert!(erased.is_some());
2980        assert_eq!(unsafe { &*erased.unwrap() }.value, 2);
2981        assert_eq!(list.len(), 2);
2982
2983        let mut iter = list.iter();
2984        assert_eq!(iter.next().unwrap().value, 1);
2985        assert_eq!(iter.next().unwrap().value, 3);
2986        assert!(iter.next().is_none());
2987
2988        list.as_mut().clear();
2989    }
2990
2991    #[test]
2992    fn test_remove_from_container() {
2993        stack_pin_init!(let list = DoublyLinkedList::<*mut TestObject>::new());
2994        let mut obj1 = TestObject::new(1);
2995        let mut obj2 = TestObject::new(2);
2996        let mut obj3 = TestObject::new(3);
2997
2998        // Case 1: Attempt to remove an element not in any container
2999        let removed = unsafe {
3000            remove_from_container::<TestObject, DefaultObjectTag, *mut TestObject>(&obj1)
3001        };
3002        assert!(removed.is_none());
3003
3004        unsafe {
3005            list.as_mut().push_back_raw(&mut obj1);
3006            list.as_mut().push_back_raw(&mut obj2);
3007            list.as_mut().push_back_raw(&mut obj3);
3008        }
3009
3010        // Case 2: Remove middle (obj2)
3011        let removed = unsafe {
3012            remove_from_container::<TestObject, DefaultObjectTag, *mut TestObject>(&obj2)
3013        };
3014        assert!(removed.is_some());
3015        assert_eq!(unsafe { &*removed.unwrap() }.value, 2);
3016
3017        let mut iter = list.iter();
3018        assert_eq!(iter.next().unwrap().value, 1);
3019        assert_eq!(iter.next().unwrap().value, 3);
3020        assert!(iter.next().is_none());
3021
3022        // Case 3: Remove head (obj1)
3023        let removed = unsafe {
3024            remove_from_container::<TestObject, DefaultObjectTag, *mut TestObject>(&obj1)
3025        };
3026        assert!(removed.is_some());
3027        assert_eq!(unsafe { &*removed.unwrap() }.value, 1);
3028
3029        let mut iter = list.iter();
3030        assert_eq!(iter.next().unwrap().value, 3);
3031        assert!(iter.next().is_none());
3032
3033        // Case 4: Remove last remaining element (obj3 -> leaves empty!)
3034        let removed = unsafe {
3035            remove_from_container::<TestObject, DefaultObjectTag, *mut TestObject>(&obj3)
3036        };
3037        assert!(removed.is_some());
3038        assert_eq!(unsafe { &*removed.unwrap() }.value, 3);
3039        assert!(list.is_empty());
3040
3041        list.as_mut().clear();
3042    }
3043
3044    #[test]
3045    fn test_replace() {
3046        stack_pin_init!(let list =
3047            DoublyLinkedList::<*mut TestObject, DefaultObjectTag, TrackingSize>::new());
3048        let mut obj1 = TestObject::new(1);
3049        let mut obj2 = TestObject::new(2);
3050        let mut obj3 = TestObject::new(3);
3051
3052        unsafe {
3053            list.as_mut().push_back_raw(&mut obj1);
3054            list.as_mut().push_back_raw(&mut obj2);
3055        }
3056
3057        assert_eq!(list.len(), 2);
3058
3059        let old = unsafe { list.as_mut().replace_raw(&obj2, &mut obj3) };
3060        assert!(old.is_some());
3061        assert_eq!(unsafe { &*old.unwrap() }.value, 2);
3062        assert_eq!(list.len(), 2);
3063
3064        let mut iter = list.iter();
3065        assert_eq!(iter.next().unwrap().value, 1);
3066        assert_eq!(iter.next().unwrap().value, 3);
3067        assert!(iter.next().is_none());
3068
3069        list.as_mut().clear();
3070    }
3071
3072    #[test]
3073    fn test_cursor_replace() {
3074        stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<UniqueTestObject>>::new());
3075
3076        let obj1 = UniquePtr::try_new(UniqueTestObject::new(1)).unwrap();
3077        let obj2 = UniquePtr::try_new(UniqueTestObject::new(2)).unwrap();
3078        let obj3 = UniquePtr::try_new(UniqueTestObject::new(3)).unwrap();
3079
3080        list.as_mut().push_back(obj1);
3081        list.as_mut().push_back(obj2);
3082
3083        let mut cursor = list.as_mut().cursor_front_mut();
3084        cursor.move_next(); // point to obj2
3085
3086        let old = cursor.replace(obj3);
3087        assert!(old.is_some());
3088        assert_eq!(old.unwrap().value, 2);
3089
3090        let mut iter = list.iter();
3091        assert_eq!(iter.next().unwrap().value, 1);
3092        assert_eq!(iter.next().unwrap().value, 3);
3093        assert!(iter.next().is_none());
3094
3095        list.as_mut().clear();
3096    }
3097
3098    struct Tag2;
3099
3100    #[fbl::ref_counted]
3101    #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
3102    #[repr(C)]
3103    struct MultiListObject {
3104        value: i32,
3105        #[dll_node]
3106        node1: DoublyLinkedListNode<MultiListObject>,
3107        #[dll_node(tag = Tag2)]
3108        node2: DoublyLinkedListNode<MultiListObject>,
3109    }
3110
3111    #[test]
3112    fn test_multiple_containers() {
3113        stack_pin_init!(let list1 =
3114            DoublyLinkedList::<RefPtr<MultiListObject>, DefaultObjectTag>::new());
3115        stack_pin_init!(let list2 = DoublyLinkedList::<RefPtr<MultiListObject>, Tag2>::new());
3116
3117        let obj1 = fbl::make_ref_counted!(MultiListObject {
3118            value: 1,
3119            node1: DoublyLinkedListNode::new(),
3120            node2: DoublyLinkedListNode::new(),
3121        })
3122        .unwrap();
3123
3124        let obj2 = fbl::make_ref_counted!(MultiListObject {
3125            value: 2,
3126            node1: DoublyLinkedListNode::new(),
3127            node2: DoublyLinkedListNode::new(),
3128        })
3129        .unwrap();
3130
3131        list1.as_mut().push_back(obj1.clone());
3132        list1.as_mut().push_back(obj2.clone());
3133
3134        list2.as_mut().push_back(obj2); // obj2 is now in both lists!
3135
3136        let mut iter1 = list1.iter();
3137        assert_eq!(iter1.next().unwrap().value, 1);
3138        assert_eq!(iter1.next().unwrap().value, 2);
3139        assert!(iter1.next().is_none());
3140
3141        let mut iter2 = list2.iter();
3142        assert_eq!(iter2.next().unwrap().value, 2);
3143        assert!(iter2.next().is_none());
3144
3145        list1.as_mut().clear();
3146        list2.as_mut().clear();
3147    }
3148
3149    use alloc::sync::Arc;
3150    use core::sync::atomic::{AtomicBool, Ordering};
3151
3152    #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
3153    struct LifecycleObject {
3154        destroyed: Arc<AtomicBool>,
3155        #[dll_node]
3156        node: DoublyLinkedListNode<LifecycleObject>,
3157    }
3158
3159    impl LifecycleObject {
3160        fn new(destroyed: Arc<AtomicBool>) -> Self {
3161            Self { destroyed, node: DoublyLinkedListNode::new() }
3162        }
3163    }
3164
3165    impl Drop for LifecycleObject {
3166        fn drop(&mut self) {
3167            self.destroyed.store(true, Ordering::Relaxed);
3168        }
3169    }
3170
3171    #[test]
3172    fn test_lifecycle_on_drop() {
3173        let destroyed1 = Arc::new(AtomicBool::new(false));
3174        let destroyed2 = Arc::new(AtomicBool::new(false));
3175
3176        {
3177            stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<LifecycleObject>>::new());
3178
3179            let obj1 = UniquePtr::try_new(LifecycleObject::new(destroyed1.clone())).unwrap();
3180            let obj2 = UniquePtr::try_new(LifecycleObject::new(destroyed2.clone())).unwrap();
3181
3182            list.as_mut().push_back(obj1);
3183            list.as_mut().push_back(obj2);
3184
3185            assert!(!destroyed1.load(Ordering::Relaxed));
3186            assert!(!destroyed2.load(Ordering::Relaxed));
3187        } // list drops here
3188
3189        assert!(destroyed1.load(Ordering::Relaxed));
3190        assert!(destroyed2.load(Ordering::Relaxed));
3191    }
3192
3193    #[test]
3194    fn test_sized_managed_list() {
3195        stack_pin_init!(let list =
3196            DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
3197
3198        assert_eq!(list.len(), 0);
3199
3200        let obj1 = UniquePtr::try_new(UniqueTestObject::new(1)).unwrap();
3201        let obj2 = UniquePtr::try_new(UniqueTestObject::new(2)).unwrap();
3202
3203        list.as_mut().push_back(obj1);
3204        assert_eq!(list.len(), 1);
3205
3206        list.as_mut().push_back(obj2);
3207        assert_eq!(list.len(), 2);
3208
3209        let popped = list.as_mut().pop_front();
3210        assert!(popped.is_some());
3211        assert_eq!(list.len(), 1);
3212
3213        list.as_mut().clear();
3214        assert_eq!(list.len(), 0);
3215    }
3216
3217    #[test]
3218    fn test_unidirectional_iterators() {
3219        stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<UniqueTestObject>>::new());
3220
3221        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
3222        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
3223        list.as_mut().push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
3224
3225        // 1. Test ForwardIterator from beginning
3226        let mut f_iter = list.forward_iter();
3227        assert_eq!(f_iter.next().unwrap().value, 1);
3228        assert_eq!(f_iter.next().unwrap().value, 2);
3229        assert_eq!(f_iter.next().unwrap().value, 3);
3230        assert!(f_iter.next().is_none());
3231
3232        // 2. Test ReverseIterator from end
3233        let mut r_iter = list.reverse_iter();
3234        assert_eq!(r_iter.next().unwrap().value, 3);
3235        assert_eq!(r_iter.next().unwrap().value, 2);
3236        assert_eq!(r_iter.next().unwrap().value, 1);
3237        assert!(r_iter.next().is_none());
3238
3239        list.as_mut().clear();
3240    }
3241
3242    #[test]
3243    fn test_cursor_at() {
3244        stack_pin_init!(let list =
3245            DoublyLinkedList::<*mut TestObject, DefaultObjectTag, TrackingSize>::new());
3246        let mut obj1 = TestObject::new(1);
3247        let mut obj2 = TestObject::new(2);
3248        let mut obj3 = TestObject::new(3);
3249
3250        unsafe {
3251            list.as_mut().push_back_raw(&mut obj1);
3252            list.as_mut().push_back_raw(&mut obj2);
3253            list.as_mut().push_back_raw(&mut obj3);
3254        }
3255
3256        // Create a cursor at the second element (obj2).
3257        // SAFETY: `obj2` is a member of `list`.
3258        let mut cursor = unsafe { list.as_mut().cursor_at(&obj2) };
3259        assert_eq!(cursor.get().unwrap().value, 2);
3260
3261        // Verify we can move next.
3262        cursor.move_next();
3263        assert_eq!(cursor.get().unwrap().value, 3);
3264
3265        // Verify we can move prev from the original position.
3266        // SAFETY: `obj2` is a member of `list`.
3267        let mut cursor = unsafe { list.as_mut().cursor_at(&obj2) };
3268        cursor.move_prev();
3269        assert_eq!(cursor.get().unwrap().value, 1);
3270
3271        // Verify we can erase via the cursor created at the element.
3272        // SAFETY: `obj2` is a member of `list`.
3273        let mut cursor = unsafe { list.as_mut().cursor_at(&obj2) };
3274        let erased = cursor.erase().unwrap();
3275        assert_eq!(unsafe { &*erased }.value, 2);
3276
3277        // Verify list contents after erase.
3278        let mut iter = list.iter();
3279        assert_eq!(iter.next().unwrap().value, 1);
3280        assert_eq!(iter.next().unwrap().value, 3);
3281        assert!(iter.next().is_none());
3282
3283        list.as_mut().clear();
3284    }
3285
3286    // FFI Declarations
3287    unsafe extern "C" {
3288        // UniqueList Helpers
3289        fn cpp_create_unique_list() -> *mut c_void;
3290        fn cpp_destroy_unique_list(list: *mut c_void);
3291        fn cpp_unique_list_push_back(list: *mut c_void, item: *mut c_void);
3292        fn cpp_unique_list_pop_front(list: *mut c_void) -> *mut c_void;
3293        fn cpp_unique_list_is_empty(list: *mut c_void) -> bool;
3294
3295        // RefList Helpers
3296        fn cpp_create_ref_list() -> *mut c_void;
3297        fn cpp_destroy_ref_list(list: *mut c_void);
3298        fn cpp_ref_list_push_back(list: *mut c_void, item: *mut c_void);
3299        fn cpp_ref_list_pop_front(list: *mut c_void) -> *mut c_void;
3300        fn cpp_ref_list_is_empty(list: *mut c_void) -> bool;
3301
3302        // SharedUniqueObject Helpers
3303        fn cpp_create_unique_object(value: i32, destruction_flag: *mut bool) -> *mut c_void;
3304        fn cpp_get_unique_object_value(obj: *mut c_void) -> i32;
3305
3306        // SharedRefObject Helpers
3307        fn cpp_create_ref_object(value: i32, destruction_flag: *mut bool) -> *mut c_void;
3308        fn cpp_get_ref_object_value(obj: *mut c_void) -> i32;
3309    }
3310
3311    #[test]
3312    fn test_interop_rust_list_cpp_unique_objects() {
3313        let destroyed1 = AtomicBool::new(false);
3314        let destroyed2 = AtomicBool::new(false);
3315
3316        unsafe {
3317            stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<SharedUniqueObject>>::new());
3318
3319            let cpp_raw1 = cpp_create_unique_object(1, destroyed1.as_ptr() as *mut bool);
3320            let cpp_raw2 = cpp_create_unique_object(2, destroyed2.as_ptr() as *mut bool);
3321
3322            let obj1 = UniquePtr::from_raw(cpp_raw1 as *mut SharedUniqueObject);
3323            let obj2 = UniquePtr::from_raw(cpp_raw2 as *mut SharedUniqueObject);
3324
3325            list.as_mut().push_back(obj1);
3326            list.as_mut().push_back(obj2);
3327
3328            assert!(!destroyed1.load(Ordering::Relaxed));
3329            assert!(!destroyed2.load(Ordering::Relaxed));
3330
3331            // Pop one
3332            let popped = list.as_mut().pop_front();
3333            assert!(popped.is_some());
3334            assert_eq!(popped.as_ref().unwrap().value, 1);
3335
3336            // Drop popped -> should destroy in C++!
3337            drop(popped);
3338            assert!(destroyed1.load(Ordering::Relaxed));
3339            assert!(!destroyed2.load(Ordering::Relaxed));
3340
3341            // Drop list -> should destroy remaining in C++!
3342        }
3343        assert!(destroyed2.load(Ordering::Relaxed));
3344    }
3345
3346    #[test]
3347    fn test_interop_cpp_list_rust_unique_objects() {
3348        let destroyed1 = Arc::new(AtomicBool::new(false));
3349        let destroyed2 = Arc::new(AtomicBool::new(false));
3350
3351        unsafe {
3352            let cpp_list = cpp_create_unique_list();
3353            assert!(cpp_unique_list_is_empty(cpp_list));
3354
3355            let obj1 = UniquePtr::try_new(SharedUniqueObject::new(1)).unwrap();
3356            let obj2 = UniquePtr::try_new(SharedUniqueObject::new(2)).unwrap();
3357
3358            // Set destruction flags
3359            let raw1 = UniquePtr::as_ptr(&obj1) as *mut SharedUniqueObject;
3360            (*raw1).destruction_flag = destroyed1.as_ptr() as *mut bool;
3361            let raw2 = UniquePtr::as_ptr(&obj2) as *mut SharedUniqueObject;
3362            (*raw2).destruction_flag = destroyed2.as_ptr() as *mut bool;
3363
3364            // Push to C++ list (transfers ownership)
3365            cpp_unique_list_push_back(cpp_list, UniquePtr::into_raw(obj1) as *mut c_void);
3366            cpp_unique_list_push_back(cpp_list, UniquePtr::into_raw(obj2) as *mut c_void);
3367
3368            assert!(!destroyed1.load(Ordering::Relaxed));
3369            assert!(!destroyed2.load(Ordering::Relaxed));
3370
3371            // Pop one from C++
3372            let popped = cpp_unique_list_pop_front(cpp_list);
3373            assert!(!popped.is_null());
3374            assert_eq!(cpp_get_unique_object_value(popped), 1);
3375
3376            // Convert back to Rust UniquePtr and drop -> should free in Rust!
3377            let popped_rust = UniquePtr::from_raw(popped as *mut SharedUniqueObject);
3378            drop(popped_rust);
3379            assert!(destroyed1.load(Ordering::Relaxed));
3380            assert!(!destroyed2.load(Ordering::Relaxed));
3381
3382            // Destroy C++ list -> should destroy remaining in Rust!
3383            cpp_destroy_unique_list(cpp_list);
3384        }
3385        assert!(destroyed2.load(Ordering::Relaxed));
3386    }
3387
3388    #[test]
3389    fn test_interop_rust_list_cpp_ref_objects() {
3390        let destroyed1 = AtomicBool::new(false);
3391        let destroyed2 = AtomicBool::new(false);
3392
3393        unsafe {
3394            stack_pin_init!(let list = DoublyLinkedList::<RefPtr<SharedRefObject>>::new());
3395
3396            let cpp_raw1 = cpp_create_ref_object(1, destroyed1.as_ptr() as *mut bool);
3397            let cpp_raw2 = cpp_create_ref_object(2, destroyed2.as_ptr() as *mut bool);
3398
3399            let obj1 = RefPtr::from_raw(cpp_raw1 as *mut SharedRefObject);
3400            let obj2 = RefPtr::from_raw(cpp_raw2 as *mut SharedRefObject);
3401
3402            list.as_mut().push_back(obj1);
3403            list.as_mut().push_back(obj2);
3404
3405            assert!(!destroyed1.load(Ordering::Relaxed));
3406            assert!(!destroyed2.load(Ordering::Relaxed));
3407
3408            // Pop one
3409            let popped = list.as_mut().pop_front();
3410            assert!(popped.is_some());
3411            assert_eq!(popped.as_ref().unwrap().value, 1);
3412
3413            // Drop popped -> should destroy in C++!
3414            drop(popped);
3415            assert!(destroyed1.load(Ordering::Relaxed));
3416            assert!(!destroyed2.load(Ordering::Relaxed));
3417
3418            // Drop list -> should destroy remaining in C++!
3419        }
3420        assert!(destroyed2.load(Ordering::Relaxed));
3421    }
3422
3423    #[test]
3424    fn test_interop_cpp_list_rust_ref_objects() {
3425        let destroyed1 = Arc::new(AtomicBool::new(false));
3426        let destroyed2 = Arc::new(AtomicBool::new(false));
3427
3428        unsafe {
3429            let cpp_list = cpp_create_ref_list();
3430            assert!(cpp_ref_list_is_empty(cpp_list));
3431
3432            let obj1 = SharedRefObject::new_ref_counted(1);
3433            let obj2 = SharedRefObject::new_ref_counted(2);
3434
3435            // Set destruction flags
3436            let raw1 = RefPtr::as_ptr(&obj1) as *mut SharedRefObject;
3437            (*raw1).destruction_flag = destroyed1.as_ptr() as *mut bool;
3438            let raw2 = RefPtr::as_ptr(&obj2) as *mut SharedRefObject;
3439            (*raw2).destruction_flag = destroyed2.as_ptr() as *mut bool;
3440
3441            // Push to C++ list (transfers ownership)
3442            cpp_ref_list_push_back(
3443                cpp_list,
3444                RefPtr::into_raw(obj1) as *mut SharedRefObject as *mut c_void,
3445            );
3446            cpp_ref_list_push_back(
3447                cpp_list,
3448                RefPtr::into_raw(obj2) as *mut SharedRefObject as *mut c_void,
3449            );
3450
3451            assert!(!destroyed1.load(Ordering::Relaxed));
3452            assert!(!destroyed2.load(Ordering::Relaxed));
3453
3454            // Pop one from C++
3455            let popped = cpp_ref_list_pop_front(cpp_list);
3456            assert!(!popped.is_null());
3457            assert_eq!(cpp_get_ref_object_value(popped), 1);
3458
3459            // Convert back to Rust RefPtr and drop -> should free in Rust!
3460            let popped_rust = RefPtr::from_raw(popped as *mut SharedRefObject);
3461            drop(popped_rust);
3462            assert!(destroyed1.load(Ordering::Relaxed));
3463            assert!(!destroyed2.load(Ordering::Relaxed));
3464
3465            // Destroy C++ list -> should destroy remaining in Rust!
3466            cpp_destroy_ref_list(cpp_list);
3467        }
3468        assert!(destroyed2.load(Ordering::Relaxed));
3469    }
3470}