Skip to main content

embed_seglist/
seglist.rs

1//! SegList : A segmented list with cache-friendly node sizes.
2//!
3//! Support push() / pop() from the tail, and one-time consume all elements.
4//! It does not support random access.
5//!
6//! Each segment's capacity is calculated at runtime based on T's size
7//! to fit within a cache line. (The first segment is 2* CACHE_LINE_SIZE, the subsequent allocation
8//! use CACHE_LINE_SIZE * 4)
9//!
10//! It's faster than Vec when the number of items is small (1~64), because it does not re-allocate
11//! during `push()`. It's slower than Vec when the number is very large (due to pointer dereference cost).
12//!
13//! # NOTE
14//!
15//! T is allow to larger than `2 * CACHE_LINE_SIZE`, in this case `SegList` will ensure at least 2
16//! items in one segment. But it's not efficient when T larger than 64B, you should consider put T into Box.
17//!
18//! # Example
19//!
20//! ```rust
21//! use embed_seglist::SegList;
22//!
23//! // Create a new SegList
24//! let mut list: SegList<i32> = SegList::new();
25//!
26//! // Push elements to the back
27//! list.push(10);
28//! list.push(20);
29//! list.push(30);
30//!
31//! assert_eq!(list.len(), 3);
32//! assert_eq!(list.first(), Some(&10));
33//! assert_eq!(list.last(), Some(&30));
34//!
35//! // Pop elements from the back (LIFO order)
36//! assert_eq!(list.pop(), Some(30));
37//! assert_eq!(list.pop(), Some(20));
38//! assert_eq!(list.pop(), Some(10));
39//! assert_eq!(list.pop(), None);
40//! assert!(list.is_empty());
41//!
42//! // Iterate over elements
43//! list.push(1);
44//! list.push(2);
45//! list.push(3);
46//! let sum: i32 = list.iter().sum();
47//! assert_eq!(sum, 6);
48//!
49//! // Mutable iteration
50//! for item in list.iter_mut() {
51//!     *item *= 10;
52//! }
53//! assert_eq!(list.last(), Some(&30));
54//!
55//! // Drain all elements (consumes the list)
56//! let drained: Vec<i32> = list.into_iter().collect();
57//! assert_eq!(drained, vec![10, 20, 30]);
58//! ```
59
60use alloc::alloc::{alloc, dealloc, handle_alloc_error};
61use core::alloc::Layout;
62use core::fmt;
63use core::mem::{MaybeUninit, align_of, needs_drop, size_of};
64use core::ptr::{NonNull, null_mut};
65use embed_collections::CACHE_LINE_SIZE;
66
67/// Segmented list with cache-friendly segment sizes.
68///
69/// Support push() / pop() from the tail, and one-time consume all elements.
70/// It does not support random access.
71///
72/// Each segment's capacity is calculated at runtime based on T's size
73/// to fit within a cache line. (The first segment is 2 * CACHE_LINE_SIZE, the subsequent allocation
74/// use CACHE_LINE_SIZE * 4)
75///
76/// It's faster than Vec when the number of items is small (1~64), because it does not re-allocate
77/// during `push()`. It's slower than Vec when the number is very large (due to pointer dereference cost).
78///
79/// # NOTE
80///
81/// T is allow to larger than `2 * CACHE_LINE_SIZE`, in this case SegList will ensure at least 2
82/// items in one segment. But it's not efficient when T larger than 128B, you should consider put T into Box.
83///
84/// Refer to [module level](crate) doc for examples.
85pub struct SegList<T> {
86    /// Pointer to the last segment (tail.get_header().next points to first element), to reduce the main struct size
87    tail: NonNull<SegHeader<T>>,
88    /// Total number of elements in the list
89    count: usize,
90}
91
92unsafe impl<T: Send> Send for SegList<T> {}
93unsafe impl<T: Send> Sync for SegList<T> {}
94
95impl<T> SegList<T> {
96    /// Create a new empty SegList with one allocated segment
97    pub fn new() -> Self {
98        let mut seg = unsafe { Segment::<T>::alloc(null_mut(), null_mut(), true) };
99        let header_ptr = seg.header.as_ptr();
100        let header = seg.get_header_mut();
101        // Make it circular: tail.next points to head (itself for now)
102        header.next = header_ptr;
103        Self { tail: seg.header, count: 0 }
104    }
105
106    /// Returns true if the list is empty
107    #[inline(always)]
108    pub fn is_empty(&self) -> bool {
109        self.count == 0
110    }
111
112    /// Get the base capacity of the first segment
113    #[inline(always)]
114    pub const fn segment_cap() -> usize {
115        Segment::<T>::base_cap()
116    }
117
118    /// Returns the total number of elements in the list
119    #[inline(always)]
120    pub fn len(&self) -> usize {
121        self.count
122    }
123
124    /// Push an element to the back of the list
125    #[inline]
126    pub fn push(&mut self, item: T) {
127        unsafe {
128            let mut tail_seg = Segment::from_raw(self.tail);
129            if tail_seg.is_full() {
130                let tail_ptr = tail_seg.header.as_ptr();
131                let cur = tail_seg.get_header_mut();
132                // Subsequent segments use LARGE_LAYOUT (cacheline * 2)
133                let new_seg = Segment::alloc(tail_ptr, cur.next, false);
134                cur.next = new_seg.header.as_ptr();
135                self.tail = new_seg.header;
136                tail_seg = new_seg;
137            }
138            tail_seg.push(item);
139        }
140        self.count += 1;
141    }
142
143    /// Pop an element from the back of the list
144    #[inline]
145    pub fn pop(&mut self) -> Option<T> {
146        if self.count == 0 {
147            return None;
148        }
149        unsafe {
150            let mut tail_seg = Segment::from_raw(self.tail);
151            let (item, is_empty) = tail_seg.pop();
152            if is_empty {
153                let cur = tail_seg.get_header_mut();
154                let first_ptr = cur.next;
155                let cur_prev = cur.prev;
156                if self.tail.as_ptr() != first_ptr && !cur_prev.is_null() {
157                    // More than one segment: remove tail segment
158                    self.tail = NonNull::new_unchecked(cur_prev);
159                    (*self.tail.as_ptr()).next = first_ptr;
160                    tail_seg.dealloc();
161                }
162                // If only one segment, keep it for future use
163            }
164            self.count -= 1;
165            Some(item)
166        }
167    }
168
169    // Break the cycle and free all segments
170    #[inline(always)]
171    fn break_first_node(&mut self) -> Segment<T> {
172        let tail_header = unsafe { self.tail.as_mut() };
173        let first = tail_header.next;
174        tail_header.next = null_mut();
175        unsafe { Segment::from_raw(NonNull::new_unchecked(first)) }
176    }
177
178    #[inline(always)]
179    fn first_ptr(&self) -> NonNull<SegHeader<T>> {
180        // SAFETY: tail always points to a valid segment with at least one element.
181        // get first segment through next ptr from the tail
182        unsafe {
183            let tail_header = self.tail.as_ref();
184            let first = tail_header.next;
185            NonNull::new_unchecked(first)
186        }
187    }
188
189    /// Returns an iterator over the list
190    #[inline]
191    pub fn iter(&self) -> SegListIter<'_, T> {
192        let first_seg = unsafe { Segment::from_raw(self.first_ptr()) };
193        SegListIter {
194            base: IterBase { cur: first_seg, cur_idx: 0, remaining: self.count, forward: true },
195            _marker: core::marker::PhantomData,
196        }
197    }
198
199    /// Returns a reverse iterator over the list
200    #[inline]
201    pub fn iter_rev(&self) -> SegListIter<'_, T> {
202        let tail_seg = unsafe { Segment::from_raw(self.tail) };
203        let tail_header = tail_seg.get_header();
204        let start_idx = if tail_header.count > 0 { tail_header.count as usize - 1 } else { 0 };
205        SegListIter {
206            base: IterBase {
207                cur: tail_seg,
208                cur_idx: start_idx,
209                remaining: self.count,
210                forward: false,
211            },
212            _marker: core::marker::PhantomData,
213        }
214    }
215
216    /// Returns a mutable iterator over the list
217    #[inline]
218    pub fn iter_mut(&mut self) -> SegListIterMut<'_, T> {
219        let first_seg = unsafe { Segment::from_raw(self.first_ptr()) };
220        SegListIterMut {
221            base: IterBase { cur: first_seg, cur_idx: 0, remaining: self.count, forward: true },
222            _marker: core::marker::PhantomData,
223        }
224    }
225
226    /// Returns a mutable reverse iterator over the list
227    #[inline]
228    pub fn iter_mut_rev(&mut self) -> SegListIterMut<'_, T> {
229        let tail_seg = unsafe { Segment::from_raw(self.tail) };
230        let tail_header = tail_seg.get_header();
231        let start_idx = if tail_header.count > 0 { tail_header.count as usize - 1 } else { 0 };
232        SegListIterMut {
233            base: IterBase {
234                cur: tail_seg,
235                cur_idx: start_idx,
236                remaining: self.count,
237                forward: false,
238            },
239            _marker: core::marker::PhantomData,
240        }
241    }
242
243    /// Returns a draining iterator that consumes the list and yields elements from tail to head
244    pub fn into_iter_rev(mut self) -> SegListIntoIter<T> {
245        // break the cycle
246        let mut first = self.break_first_node();
247        let remaining = self.count;
248        let (cur, start_idx) = if self.count == 0 {
249            unsafe {
250                first.dealloc();
251            }
252            (None, 0)
253        } else {
254            let tail_seg = unsafe { Segment::from_raw(self.tail) };
255            let tail_header = tail_seg.get_header();
256            let start_idx = if tail_header.count > 0 { tail_header.count as usize - 1 } else { 0 };
257            (Some(tail_seg), start_idx)
258        };
259        core::mem::forget(self);
260        SegListIntoIter { cur, cur_idx: start_idx, forward: false, remaining }
261    }
262
263    /// Returns a reference to the first element in the list
264    #[inline]
265    pub fn first(&self) -> Option<&T> {
266        if self.count == 0 {
267            return None;
268        }
269        // SAFETY: tail always points to a valid segment with at least one element.
270        // get first segment through next ptr from the tail
271        unsafe {
272            let first_seg = Segment::from_raw(self.first_ptr());
273            Some((*first_seg.item_ptr(0)).assume_init_ref())
274        }
275    }
276
277    /// Returns a mut reference to the first element in the list
278    #[inline]
279    pub fn first_mut(&self) -> Option<&T> {
280        if self.count == 0 {
281            return None;
282        }
283        // SAFETY: tail always points to a valid segment with at least one element.
284        // get first segment through next ptr from the tail
285        unsafe {
286            let first_seg = Segment::from_raw(self.first_ptr());
287            Some((*first_seg.item_ptr(0)).assume_init_mut())
288        }
289    }
290
291    /// Returns a reference to the last element in the list
292    #[inline]
293    pub fn last(&self) -> Option<&T> {
294        // SAFETY: tail always points to a valid segment with at least one element
295        unsafe {
296            let tail_seg = Segment::from_raw(self.tail);
297            let header = tail_seg.get_header();
298            if header.count == 0 {
299                return None;
300            }
301            let idx = (header.count - 1) as usize;
302            Some((*tail_seg.item_ptr(idx)).assume_init_ref())
303        }
304    }
305
306    /// Returns a mutable reference to the last element in the list
307    #[inline]
308    pub fn last_mut(&mut self) -> Option<&mut T> {
309        // SAFETY: tail always points to a valid segment with at least one element
310        unsafe {
311            let tail_seg = Segment::from_raw(self.tail);
312            let header = tail_seg.get_header();
313            if header.count == 0 {
314                return None;
315            }
316            let idx = (header.count - 1) as usize;
317            Some((*tail_seg.item_ptr(idx)).assume_init_mut())
318        }
319    }
320
321    /// Clear all elements from the list
322    #[inline(always)]
323    pub fn clear(&mut self) {
324        if self.count == 0 {
325            return;
326        }
327        unsafe {
328            let tail_header = self.tail.as_mut();
329            let first = tail_header.next;
330            let mut cur = Segment::from_raw(self.tail);
331            loop {
332                let next = cur.get_header().prev;
333                if next.is_null() {
334                    if needs_drop::<T>() {
335                        cur.drop_items();
336                    }
337                    self.count = 0;
338                    let header = cur.get_header_mut();
339                    header.count = 0;
340                    header.next = first;
341                    self.tail = NonNull::new_unchecked(first);
342                    return;
343                } else {
344                    cur.dealloc_with_items();
345                    cur = Segment::from_raw(NonNull::new_unchecked(next));
346                }
347            }
348        }
349    }
350}
351
352impl<T> Default for SegList<T> {
353    fn default() -> Self {
354        Self::new()
355    }
356}
357
358impl<T> Drop for SegList<T> {
359    fn drop(&mut self) {
360        // Break the cycle and get the first segment
361        let mut cur = self.break_first_node();
362        loop {
363            // Save next pointer before dealloc
364            let next = cur.get_header().next;
365            unsafe { cur.dealloc_with_items() };
366            if next.is_null() {
367                break;
368            }
369            cur = unsafe { Segment::from_raw(NonNull::new_unchecked(next)) };
370        }
371    }
372}
373
374impl<T> IntoIterator for SegList<T> {
375    type Item = T;
376    type IntoIter = SegListIntoIter<T>;
377
378    #[inline(always)]
379    fn into_iter(mut self) -> Self::IntoIter {
380        // Break the cycle and get the first segment
381        let mut first = self.break_first_node();
382        let remaining = self.count;
383        let cur = if self.count == 0 {
384            unsafe {
385                first.dealloc();
386            }
387            None
388        } else {
389            Some(first)
390        };
391        // To prevent drop from being called
392        core::mem::forget(self);
393        SegListIntoIter { cur, cur_idx: 0, forward: true, remaining }
394    }
395}
396
397impl<'a, T> IntoIterator for &'a SegList<T> {
398    type Item = &'a T;
399    type IntoIter = SegListIter<'a, T>;
400
401    #[inline(always)]
402    fn into_iter(self) -> Self::IntoIter {
403        self.iter()
404    }
405}
406
407impl<'a, T> IntoIterator for &'a mut SegList<T> {
408    type Item = &'a mut T;
409    type IntoIter = SegListIterMut<'a, T>;
410
411    #[inline(always)]
412    fn into_iter(self) -> Self::IntoIter {
413        self.iter_mut()
414    }
415}
416
417impl<T: fmt::Debug> fmt::Debug for SegList<T> {
418    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419        f.debug_struct("SegList").field("len", &self.len()).finish()
420    }
421}
422
423/// Segment header containing metadata
424#[repr(C)]
425struct SegHeader<T> {
426    /// Count of valid elements in this segment
427    count: u32,
428    /// Capacity of this segment (may vary for different segments)
429    cap: u32,
430    prev: *mut SegHeader<T>,
431    /// Next segment in the list
432    next: *mut SegHeader<T>,
433    _marker: core::marker::PhantomData<T>,
434}
435
436/// A segment containing header and element storage
437struct Segment<T> {
438    /// Pointer to the header
439    header: NonNull<SegHeader<T>>,
440}
441
442unsafe impl<T: Send> Send for Segment<T> {}
443
444impl<T> Segment<T> {
445    // data_offset is the same for both base and large layouts
446    const DATA_OFFSET: usize = Self::calc_data_offset();
447
448    // Pre-calculate layout for cacheline-sized segment (first segment)
449    // (cap, layout)
450    const BASE_LAYOUT: (usize, Layout) = Self::calc_layout_const(CACHE_LINE_SIZE * 2);
451
452    // Pre-calculate layout for cacheline*2-sized segment (subsequent segments)
453    // (cap, layout)
454    const LARGE_LAYOUT: (usize, Layout) = Self::calc_layout_const(CACHE_LINE_SIZE * 4);
455
456    /// Const fn to calculate data offset (same for all segments)
457    const fn calc_data_offset() -> usize {
458        let mut data_offset = size_of::<SegHeader<T>>();
459        let t_size = size_of::<T>();
460        let t_align = align_of::<MaybeUninit<T>>();
461
462        if t_size != 0 {
463            data_offset = (data_offset + t_align - 1) & !(t_align - 1);
464        }
465        data_offset
466    }
467
468    /// Const fn to calculate layout for a given cache line size
469    const fn calc_layout_const(cache_line: usize) -> (usize, Layout) {
470        let t_size = size_of::<T>();
471        let data_offset = Self::DATA_OFFSET;
472        let capacity;
473        let final_alloc_size;
474        let final_align;
475
476        if t_size == 0 {
477            // 0-size does not actually take place
478            capacity = 1024;
479            final_alloc_size = cache_line;
480            final_align = cache_line;
481        } else {
482            let min_elements = 2;
483            let min_required_size = data_offset + (t_size * min_elements);
484            let alloc_size = (min_required_size + cache_line - 1) & !(cache_line - 1);
485            final_align = if cache_line > align_of::<MaybeUninit<T>>() {
486                cache_line
487            } else {
488                align_of::<MaybeUninit<T>>()
489            };
490            final_alloc_size = (alloc_size + final_align - 1) & !(final_align - 1);
491            capacity = (final_alloc_size - data_offset) / t_size;
492            // rust 1.57 support assert in const fn
493            assert!(capacity >= min_elements);
494        }
495
496        match Layout::from_size_align(final_alloc_size, final_align) {
497            Ok(l) => (capacity, l),
498            Err(_) => panic!("Invalid layout"),
499        }
500    }
501
502    /// Get the base capacity (first segment's capacity)
503    #[inline(always)]
504    const fn base_cap() -> usize {
505        Self::BASE_LAYOUT.0
506    }
507
508    /// Get the large capacity (subsequent segments' capacity)
509    #[inline(always)]
510    const fn large_cap() -> usize {
511        Self::LARGE_LAYOUT.0
512    }
513
514    /// Get the data offset (offset of first element from header start)
515    #[inline(always)]
516    const fn data_offset() -> usize {
517        Self::DATA_OFFSET
518    }
519
520    /// Create a new empty segment
521    /// is_first: true for first segment (uses BASE_LAYOUT), false for subsequent (uses LARGE_LAYOUT)
522    #[inline]
523    unsafe fn alloc(prev: *mut SegHeader<T>, next: *mut SegHeader<T>, is_first: bool) -> Self {
524        let (cap, layout) = if is_first {
525            (Self::base_cap() as u32, Self::BASE_LAYOUT.1)
526        } else {
527            (Self::large_cap() as u32, Self::LARGE_LAYOUT.1)
528        };
529        let ptr: *mut u8 = unsafe { alloc(layout) };
530        if ptr.is_null() {
531            handle_alloc_error(layout);
532        }
533        unsafe {
534            let p = NonNull::new_unchecked(ptr as *mut SegHeader<T>);
535            let header = p.as_ptr();
536            // Initialize header
537            (*header).count = 0;
538            (*header).cap = cap;
539            (*header).prev = prev;
540            (*header).next = next;
541            Self::from_raw(p)
542        }
543    }
544
545    #[inline(always)]
546    unsafe fn drop_items(&self) {
547        unsafe {
548            for i in 0..self.len() {
549                (*self.item_ptr(i)).assume_init_drop();
550            }
551        }
552    }
553
554    #[inline(always)]
555    unsafe fn dealloc_with_items(&mut self) {
556        unsafe {
557            if needs_drop::<T>() {
558                self.drop_items();
559            }
560            self.dealloc();
561        }
562    }
563
564    #[inline(always)]
565    unsafe fn dealloc(&mut self) {
566        // Deallocate the entire segment (header + items)
567        unsafe {
568            let cap = (*self.header.as_ptr()).cap as usize;
569            let layout =
570                if cap == Self::base_cap() { Self::BASE_LAYOUT.1 } else { Self::LARGE_LAYOUT.1 };
571            dealloc(self.header.as_ptr() as *mut u8, layout);
572        }
573    }
574
575    #[inline(always)]
576    unsafe fn from_raw(header: NonNull<SegHeader<T>>) -> Self {
577        Self { header }
578    }
579
580    /// Get the count of valid elements in this segment
581    #[inline(always)]
582    fn len(&self) -> usize {
583        unsafe { (*self.header.as_ptr()).count as usize }
584    }
585
586    #[inline(always)]
587    fn get_header(&self) -> &SegHeader<T> {
588        unsafe { self.header.as_ref() }
589    }
590
591    #[inline(always)]
592    fn get_header_mut(&mut self) -> &mut SegHeader<T> {
593        unsafe { self.header.as_mut() }
594    }
595
596    /// Check if segment has no valid elements
597    #[inline(always)]
598    fn is_empty(&self) -> bool {
599        self.len() == 0
600    }
601
602    /// Check if segment is full
603    #[inline(always)]
604    fn is_full(&self) -> bool {
605        let header = self.get_header();
606        header.count >= header.cap
607    }
608
609    /// Get pointer to item at index
610    #[inline]
611    fn item_ptr(&self, index: usize) -> *mut MaybeUninit<T> {
612        unsafe {
613            let items =
614                (self.header.as_ptr() as *mut u8).add(Self::data_offset()) as *mut MaybeUninit<T>;
615            items.add(index)
616        }
617    }
618
619    /// Push an element to this segment (if not full)
620    #[inline]
621    fn push(&mut self, item: T) {
622        debug_assert!(!self.is_full());
623        let idx = self.get_header().count as usize;
624        unsafe {
625            (*self.item_ptr(idx)).write(item);
626        }
627        self.get_header_mut().count = (idx + 1) as u32;
628    }
629
630    /// return (item, is_empty_now)
631    #[inline]
632    fn pop(&mut self) -> (T, bool) {
633        debug_assert!(!self.is_empty());
634        let idx = self.get_header().count - 1;
635        let item = unsafe { (*self.item_ptr(idx as usize)).assume_init_read() };
636        self.get_header_mut().count = idx;
637        (item, idx == 0)
638    }
639}
640
641/// Base iterator implementation shared by immutable and mutable iterators.
642/// Manages iteration state and returns raw pointers to elements.
643/// `forward` is true for forward iteration, false for backward iteration.
644struct IterBase<T> {
645    cur: Segment<T>,
646    cur_idx: usize,
647    remaining: usize,
648    forward: bool,
649}
650
651impl<T> IterBase<T> {
652    /// Advances the iterator and returns a pointer to the next element's MaybeUninit.
653    #[inline]
654    fn next(&mut self) -> Option<*mut MaybeUninit<T>> {
655        if self.remaining == 0 {
656            return None;
657        }
658        self.remaining -= 1;
659
660        if self.forward {
661            let cur_header = self.cur.get_header();
662            let idx = if self.cur_idx >= cur_header.count as usize {
663                let next = cur_header.next;
664                self.cur = unsafe { Segment::from_raw(NonNull::new_unchecked(next)) };
665                self.cur_idx = 1;
666                0
667            } else {
668                let _idx = self.cur_idx;
669                self.cur_idx = _idx + 1;
670                _idx
671            };
672            Some(self.cur.item_ptr(idx))
673        } else {
674            let idx = self.cur_idx;
675            let item_ptr = self.cur.item_ptr(idx);
676            if self.cur_idx == 0 {
677                let cur_header = self.cur.get_header();
678                if !cur_header.prev.is_null() {
679                    self.cur =
680                        unsafe { Segment::from_raw(NonNull::new_unchecked(cur_header.prev)) };
681                    let prev_header = self.cur.get_header();
682                    self.cur_idx = prev_header.count as usize - 1;
683                }
684            } else {
685                self.cur_idx -= 1;
686            }
687            Some(item_ptr)
688        }
689    }
690
691    #[inline]
692    fn size_hint(&self) -> (usize, Option<usize>) {
693        (self.remaining, Some(self.remaining))
694    }
695}
696
697/// Immutable iterator over SegList
698pub struct SegListIter<'a, T> {
699    base: IterBase<T>,
700    _marker: core::marker::PhantomData<&'a T>,
701}
702
703impl<'a, T> Iterator for SegListIter<'a, T> {
704    type Item = &'a T;
705
706    #[inline]
707    fn next(&mut self) -> Option<Self::Item> {
708        self.base.next().map(|ptr| unsafe { (*ptr).assume_init_ref() })
709    }
710
711    #[inline]
712    fn size_hint(&self) -> (usize, Option<usize>) {
713        self.base.size_hint()
714    }
715}
716
717impl<'a, T> ExactSizeIterator for SegListIter<'a, T> {}
718
719/// Mutable iterator over SegList
720pub struct SegListIterMut<'a, T> {
721    base: IterBase<T>,
722    _marker: core::marker::PhantomData<&'a mut T>,
723}
724
725impl<'a, T> Iterator for SegListIterMut<'a, T> {
726    type Item = &'a mut T;
727
728    #[inline]
729    fn next(&mut self) -> Option<Self::Item> {
730        self.base.next().map(|ptr| unsafe { (*ptr).assume_init_mut() })
731    }
732
733    #[inline]
734    fn size_hint(&self) -> (usize, Option<usize>) {
735        self.base.size_hint()
736    }
737}
738
739impl<'a, T> ExactSizeIterator for SegListIterMut<'a, T> {}
740
741/// Draining iterator over SegList
742/// Consumes elements from head to tail (FIFO order) or tail to head (LIFO order)
743pub struct SegListIntoIter<T> {
744    cur: Option<Segment<T>>,
745    cur_idx: usize,
746    forward: bool,
747    remaining: usize,
748}
749
750impl<T> Iterator for SegListIntoIter<T> {
751    type Item = T;
752
753    #[inline]
754    fn next(&mut self) -> Option<Self::Item> {
755        let cur_seg = self.cur.as_mut()?;
756        self.remaining -= 1;
757        unsafe {
758            let item = (*cur_seg.item_ptr(self.cur_idx)).assume_init_read();
759            let header = cur_seg.get_header();
760            if self.forward {
761                let next_idx = self.cur_idx + 1;
762                if next_idx >= header.count as usize {
763                    let next = header.next;
764                    cur_seg.dealloc();
765                    if next.is_null() {
766                        self.cur = None;
767                    } else {
768                        self.cur = Some(Segment::from_raw(NonNull::new_unchecked(next)));
769                        self.cur_idx = 0;
770                    }
771                } else {
772                    self.cur_idx = next_idx;
773                }
774            } else if self.cur_idx == 0 {
775                let prev = header.prev;
776                cur_seg.dealloc();
777                if prev.is_null() {
778                    self.cur = None;
779                } else {
780                    let _cur = Segment::from_raw(NonNull::new_unchecked(prev));
781                    self.cur_idx = _cur.get_header().count as usize - 1;
782                    self.cur = Some(_cur);
783                }
784            } else {
785                self.cur_idx -= 1;
786            }
787            Some(item)
788        }
789    }
790
791    #[inline]
792    fn size_hint(&self) -> (usize, Option<usize>) {
793        (self.remaining, Some(self.remaining))
794    }
795}
796
797impl<T> ExactSizeIterator for SegListIntoIter<T> {}
798
799impl<T> Drop for SegListIntoIter<T> {
800    fn drop(&mut self) {
801        if let Some(mut cur) = self.cur.take() {
802            unsafe {
803                if self.forward {
804                    // Save next pointer before dealloc
805                    let header = cur.get_header();
806                    let mut next = header.next;
807                    // Drop remaining elements in this segment (from current index to end)
808                    if needs_drop::<T>() {
809                        for i in self.cur_idx..header.count as usize {
810                            (*cur.item_ptr(i)).assume_init_drop();
811                        }
812                    }
813                    cur.dealloc();
814                    while !next.is_null() {
815                        cur = Segment::from_raw(NonNull::new_unchecked(next));
816                        next = cur.get_header().next;
817                        cur.dealloc_with_items();
818                    }
819                } else {
820                    // Save prev pointer before dealloc
821                    let mut prev = cur.get_header().prev;
822                    // Drop remaining elements in this segment (from start to current index)
823                    if needs_drop::<T>() {
824                        for i in 0..=self.cur_idx {
825                            (*cur.item_ptr(i)).assume_init_drop();
826                        }
827                    }
828                    cur.dealloc();
829                    while !prev.is_null() {
830                        cur = Segment::from_raw(NonNull::new_unchecked(prev));
831                        prev = cur.get_header().prev;
832                        cur.dealloc_with_items();
833                    }
834                }
835            }
836        }
837    }
838}
839
840#[cfg(test)]
841mod tests {
842    use super::*;
843    use embed_collections_test::{CounterI32, alive_count, reset_alive_count};
844
845    #[test]
846    fn test_multiple_segments() {
847        let mut list: SegList<i32> = SegList::new();
848        if CACHE_LINE_SIZE == 128 {
849            assert_eq!(Segment::<i32>::base_cap(), 26);
850        }
851
852        for i in 0..100 {
853            list.push(i);
854        }
855
856        assert_eq!(list.len(), 100);
857
858        for i in (0..100).rev() {
859            assert_eq!(list.pop(), Some(i));
860        }
861
862        assert_eq!(list.pop(), None);
863    }
864
865    #[test]
866    fn test_iter_single_segment() {
867        // Test with small number of elements (single segment)
868        let mut list: SegList<i32> = SegList::new();
869
870        for i in 0..10 {
871            list.push(i);
872        }
873        assert_eq!(list.first(), Some(&0));
874        assert_eq!(list.last(), Some(&9));
875
876        // Test immutable iterator
877        let collected: Vec<i32> = list.iter().copied().collect();
878        assert_eq!(collected, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
879
880        // Test mutable iterator - modify elements
881        for item in list.iter_mut() {
882            *item *= 2;
883        }
884        assert_eq!(list.first(), Some(&0));
885        assert_eq!(list.last(), Some(&18));
886
887        // Verify modification
888        let collected: Vec<i32> = list.iter().copied().collect();
889        assert_eq!(collected, vec![0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
890
891        // Test pop() - should return elements in LIFO order
892        for i in (0..10).rev() {
893            assert_eq!(list.pop(), Some(i * 2));
894        }
895        assert_eq!(list.pop(), None);
896        assert!(list.is_empty());
897    }
898
899    #[test]
900    fn test_iter_multi_segment() {
901        // Test with many elements (multiple segments)
902        let mut list: SegList<i32> = SegList::new();
903
904        for i in 0..200 {
905            list.push(i * 10);
906        }
907        assert_eq!(list.first(), Some(&0));
908        assert_eq!(list.last(), Some(&1990));
909
910        // Test immutable iterator across multiple segments
911        let collected: Vec<i32> = list.iter().copied().collect();
912        let expected: Vec<i32> = (0..200).map(|i| i * 10).collect();
913        assert_eq!(collected, expected);
914
915        // Test mutable iterator - modify elements
916        for item in list.iter_mut() {
917            *item += 1;
918        }
919        assert_eq!(list.first(), Some(&1));
920        assert_eq!(list.last(), Some(&1991));
921
922        // Verify modification
923        let collected: Vec<i32> = list.iter().copied().collect();
924        let expected: Vec<i32> = (0..200).map(|i| i * 10 + 1).collect();
925        assert_eq!(collected, expected);
926
927        // Test pop() - should return elements in LIFO order across multiple segments
928        for i in (0..200).rev() {
929            assert_eq!(list.pop(), Some(i * 10 + 1));
930        }
931        assert_eq!(list.pop(), None);
932        assert!(list.is_empty());
933    }
934
935    #[test]
936    fn test_into_iter() {
937        // Get capacity per segment for CounterI32 (i32)
938        let cap = Segment::<CounterI32>::base_cap();
939
940        // Scenario 1: Single segment, iter completely
941        {
942            reset_alive_count();
943            {
944                let mut list: SegList<CounterI32> = SegList::new();
945                // Push fewer elements than one segment capacity
946                for i in 0..5 {
947                    list.push(CounterI32::new(i));
948                }
949                assert!(list.len() < cap);
950
951                // Drain all elements
952                let drained: Vec<i32> = list.into_iter().map(|d| *d).collect();
953                assert_eq!(drained, vec![0, 1, 2, 3, 4]);
954            }
955            // All 5 elements should be dropped by drain
956            assert_eq!(alive_count(), 0);
957        }
958
959        // Scenario 2: Three segments, iter first segment partially, then drop remaining
960        {
961            reset_alive_count();
962            {
963                let mut list: SegList<CounterI32> = SegList::new();
964                // Push elements to create 3 segments (cap * 2 + 5 = more than 2 segments)
965                let total = cap * 2 + 5;
966                for i in 0..total {
967                    list.push(CounterI32::new(i as i32));
968                }
969                assert_eq!(alive_count(), cap * 2 + 5);
970
971                // Drain only half of first segment
972                let drain_count = cap / 2;
973                let mut drain_iter = list.into_iter();
974                for i in 0..drain_count {
975                    assert_eq!(*drain_iter.next().unwrap(), i as i32);
976                }
977                // Drop the drain iterator early (remaining elements should be dropped)
978                drop(drain_iter);
979            }
980            // All elements should be dropped (drained + remaining in list)
981            assert_eq!(alive_count(), 0);
982        }
983
984        // Scenario 3: Three segments, iter exactly first segment, then drop remaining
985        {
986            reset_alive_count();
987            {
988                let mut list: SegList<CounterI32> = SegList::new();
989                // Push elements to create 3 segments
990                let total = cap * 2 + 3;
991                for i in 0..total {
992                    list.push(CounterI32::new(i as i32));
993                }
994                assert_eq!(alive_count(), cap * 2 + 3);
995
996                // Drain exactly first segment
997                let mut drain_iter = list.into_iter();
998                for i in 0..cap {
999                    assert_eq!(*drain_iter.next().unwrap(), i as i32);
1000                }
1001                // Drop the drain iterator early
1002                drop(drain_iter);
1003            }
1004            // All elements should be dropped
1005            assert_eq!(alive_count(), 0);
1006        }
1007    }
1008
1009    #[test]
1010    fn test_drop_single_segment() {
1011        reset_alive_count();
1012        {
1013            let mut list: SegList<CounterI32> = SegList::new();
1014            let cap = Segment::<CounterI32>::base_cap();
1015
1016            // Push fewer elements than one segment capacity
1017            for i in 0..5 {
1018                list.push(CounterI32::new(i));
1019            }
1020            assert!(list.len() < cap);
1021            assert_eq!(alive_count(), 5);
1022
1023            // list drops here, should drop all elements
1024        }
1025
1026        assert_eq!(alive_count(), 0);
1027    }
1028
1029    #[test]
1030    fn test_drop_multi_segment() {
1031        let cap = Segment::<CounterI32>::base_cap();
1032        reset_alive_count();
1033        {
1034            let mut list: SegList<CounterI32> = SegList::new();
1035
1036            // Push elements to create multiple segments (3 segments)
1037            let total = cap * 2 + 10;
1038            for i in 0..total {
1039                list.push(CounterI32::new(i as i32));
1040            }
1041            assert_eq!(alive_count(), cap * 2 + 10);
1042            // list drops here, should drop all elements across all segments
1043        }
1044        assert_eq!(alive_count(), 0);
1045    }
1046
1047    #[test]
1048    fn test_clear_1_segment() {
1049        reset_alive_count();
1050        {
1051            let mut list: SegList<CounterI32> = SegList::new();
1052            let base_cap = Segment::<CounterI32>::base_cap();
1053
1054            for i in 0..base_cap as i32 {
1055                list.push(CounterI32::new(i));
1056            }
1057            assert_eq!(alive_count(), base_cap);
1058            list.clear();
1059            assert!(list.is_empty());
1060            assert_eq!(list.len(), 0);
1061            assert!(list.pop().is_none());
1062        }
1063        assert_eq!(alive_count(), 0);
1064    }
1065
1066    #[test]
1067    fn test_clear_2_segment() {
1068        reset_alive_count();
1069        {
1070            let mut list: SegList<CounterI32> = SegList::new();
1071
1072            let count = Segment::<CounterI32>::base_cap() + Segment::<CounterI32>::large_cap();
1073            for i in 0..count as i32 {
1074                list.push(CounterI32::new(i));
1075            }
1076            assert_eq!(alive_count(), count);
1077            list.clear();
1078            assert!(list.is_empty());
1079            assert_eq!(list.len(), 0);
1080            assert!(list.pop().is_none());
1081        }
1082        assert_eq!(alive_count(), 0);
1083    }
1084
1085    #[test]
1086    fn test_clear_3_segment() {
1087        reset_alive_count();
1088        let mut list: SegList<CounterI32> = SegList::new();
1089
1090        let count = Segment::<CounterI32>::base_cap() + Segment::<CounterI32>::large_cap() * 2;
1091        for i in 0..count as i32 {
1092            list.push(CounterI32::new(i));
1093        }
1094        assert_eq!(alive_count(), count);
1095        list.clear();
1096        assert!(list.is_empty());
1097        assert_eq!(list.len(), 0);
1098        assert!(list.pop().is_none());
1099        assert_eq!(alive_count(), 0);
1100    }
1101
1102    /// Large struct that larger than cache line
1103    #[derive(Debug, Clone, Copy, PartialEq)]
1104    struct LargeStruct {
1105        data: [u64; 16], // 128 bytes
1106    }
1107
1108    impl LargeStruct {
1109        fn new(val: u64) -> Self {
1110            Self { data: [val; 16] }
1111        }
1112    }
1113
1114    #[test]
1115    fn test_size() {
1116        println!("SegList<u64>: {}", size_of::<SegList<u64>>());
1117        println!("SegList<(u64, u32)>: {}", size_of::<SegList<(u64, u32)>>());
1118        assert_eq!(size_of::<SegHeader::<LargeStruct>>(), 24);
1119        let data_offset = Segment::<LargeStruct>::data_offset();
1120        let base_cap = Segment::<LargeStruct>::base_cap();
1121        let large_cap = Segment::<LargeStruct>::large_cap();
1122        let base_layout = Segment::<LargeStruct>::BASE_LAYOUT.1;
1123        let large_layout = Segment::<LargeStruct>::LARGE_LAYOUT.1;
1124        println!(
1125            "LargeStruct: offset={}, base(cap={} size={} align={}), large(cap={} size={} align={})",
1126            data_offset,
1127            base_cap,
1128            base_layout.size(),
1129            base_layout.align(),
1130            large_cap,
1131            large_layout.size(),
1132            large_layout.align()
1133        );
1134        let data_offset = Segment::<u64>::data_offset();
1135        let base_cap = Segment::<u64>::base_cap();
1136        let large_cap = Segment::<u64>::large_cap();
1137        let base_layout = Segment::<u64>::BASE_LAYOUT.1;
1138        let large_layout = Segment::<u64>::LARGE_LAYOUT.1;
1139        println!(
1140            "u64: offset={}, base(cap={} size={} align={}), large(cap={} size={} align={})",
1141            data_offset,
1142            base_cap,
1143            base_layout.size(),
1144            base_layout.align(),
1145            large_cap,
1146            large_layout.size(),
1147            large_layout.align()
1148        );
1149        let data_offset = Segment::<u32>::data_offset();
1150        let base_cap = Segment::<u32>::base_cap();
1151        let large_cap = Segment::<u32>::large_cap();
1152        let base_layout = Segment::<u32>::BASE_LAYOUT.1;
1153        let large_layout = Segment::<u32>::LARGE_LAYOUT.1;
1154        println!(
1155            "u32: offset={}, base(cap={} size={} align={}), large(cap={} size={} align={})",
1156            data_offset,
1157            base_cap,
1158            base_layout.size(),
1159            base_layout.align(),
1160            large_cap,
1161            large_layout.size(),
1162            large_layout.align()
1163        );
1164        let data_offset = Segment::<u16>::data_offset();
1165        let base_cap = Segment::<u16>::base_cap();
1166        let large_cap = Segment::<u16>::large_cap();
1167        let base_layout = Segment::<u16>::BASE_LAYOUT.1;
1168        let large_layout = Segment::<u16>::LARGE_LAYOUT.1;
1169        println!(
1170            "u16: offset={}, base(cap={} size={} align={}), large(cap={} size={} align={})",
1171            data_offset,
1172            base_cap,
1173            base_layout.size(),
1174            base_layout.align(),
1175            large_cap,
1176            large_layout.size(),
1177            large_layout.align()
1178        );
1179    }
1180
1181    #[test]
1182    fn test_large_type_push_pop() {
1183        let mut list: SegList<LargeStruct> = SegList::new();
1184        // Push elements - each segment can only hold a few due to large element size
1185        for i in 0..50 {
1186            list.push(LargeStruct::new(i));
1187        }
1188        assert_eq!(list.len(), 50);
1189
1190        // Pop all elements - should work correctly across multiple segments
1191        for i in (0..50).rev() {
1192            let val = list.pop().unwrap();
1193            assert_eq!(val.data[0], i);
1194            assert_eq!(val.data[7], i);
1195        }
1196        assert!(list.is_empty());
1197        assert_eq!(list.pop(), None);
1198    }
1199
1200    #[test]
1201    fn test_large_type_iter() {
1202        let mut list: SegList<LargeStruct> = SegList::new();
1203
1204        // Push elements
1205        for i in 0..30 {
1206            list.push(LargeStruct::new(i * 10));
1207        }
1208
1209        // Test iterator
1210        let collected: Vec<u64> = list.iter().map(|s| s.data[0]).collect();
1211        let expected: Vec<u64> = (0..30).map(|i| i * 10).collect();
1212        assert_eq!(collected, expected);
1213    }
1214
1215    #[test]
1216    fn test_large_type_iter_mut() {
1217        let mut list: SegList<LargeStruct> = SegList::new();
1218
1219        // Push elements
1220        for i in 0..20 {
1221            list.push(LargeStruct::new(i));
1222        }
1223
1224        // Modify through iterator
1225        for item in list.iter_mut() {
1226            item.data[0] *= 2;
1227        }
1228
1229        // Verify modification
1230        let collected: Vec<u64> = list.iter().map(|s| s.data[0]).collect();
1231        let expected: Vec<u64> = (0..20).map(|i| i * 2).collect();
1232        assert_eq!(collected, expected);
1233    }
1234
1235    #[test]
1236    fn test_large_type_drain() {
1237        let mut list: SegList<LargeStruct> = SegList::new();
1238
1239        // Push elements
1240        for i in 0..40 {
1241            list.push(LargeStruct::new(i));
1242        }
1243
1244        // Drain and verify FIFO order
1245        let drained: Vec<u64> = list.into_iter().map(|s| s.data[0]).collect();
1246        let expected: Vec<u64> = (0..40).collect();
1247        assert_eq!(drained, expected);
1248    }
1249
1250    #[test]
1251    fn test_large_type_clear() {
1252        let mut list: SegList<LargeStruct> = SegList::new();
1253
1254        // Push elements
1255        for i in 0..60 {
1256            list.push(LargeStruct::new(i));
1257        }
1258        assert_eq!(list.len(), 60);
1259
1260        // Clear
1261        list.clear();
1262        assert!(list.is_empty());
1263        assert_eq!(list.len(), 0);
1264        assert_eq!(list.pop(), None);
1265    }
1266
1267    #[test]
1268    fn test_iter_rev_single_segment() {
1269        // Test with small number of elements (single segment)
1270        let mut list: SegList<i32> = SegList::new();
1271
1272        for i in 0..10 {
1273            list.push(i);
1274        }
1275
1276        // Test reverse iterator
1277        let collected: Vec<i32> = list.iter_rev().copied().collect();
1278        let expected: Vec<i32> = (0..10).rev().collect();
1279        assert_eq!(collected, expected);
1280
1281        // Test mutable reverse iterator
1282        for item in list.iter_mut_rev() {
1283            *item *= 10;
1284        }
1285
1286        // Verify modification
1287        assert_eq!(list.first(), Some(&0));
1288        assert_eq!(list.last(), Some(&90));
1289
1290        let collected: Vec<i32> = list.iter().copied().collect();
1291        let expected: Vec<i32> = vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90];
1292        assert_eq!(collected, expected);
1293    }
1294
1295    #[test]
1296    fn test_iter_rev_multi_segment() {
1297        // Test with many elements (multiple segments)
1298        let mut list: SegList<i32> = SegList::new();
1299
1300        for i in 0..200 {
1301            list.push(i);
1302        }
1303
1304        // Test reverse iterator across multiple segments
1305        let collected: Vec<i32> = list.iter_rev().copied().collect();
1306        let expected: Vec<i32> = (0..200).rev().collect();
1307        assert_eq!(collected, expected);
1308
1309        // Test mutable reverse iterator across multiple segments
1310        for item in list.iter_mut_rev() {
1311            *item += 1000;
1312        }
1313
1314        // Verify modification
1315        assert_eq!(list.first(), Some(&1000));
1316        assert_eq!(list.last(), Some(&1199));
1317
1318        let collected: Vec<i32> = list.iter().copied().collect();
1319        let expected: Vec<i32> = (0..200).map(|i| i + 1000).collect();
1320        assert_eq!(collected, expected);
1321    }
1322
1323    #[test]
1324    fn test_iter_rev_empty() {
1325        let list: SegList<i32> = SegList::new();
1326
1327        let collected: Vec<i32> = list.iter_rev().copied().collect();
1328        assert!(collected.is_empty());
1329
1330        let mut list_mut: SegList<i32> = SegList::new();
1331        let count = list_mut.iter_mut_rev().count();
1332        assert_eq!(count, 0);
1333    }
1334
1335    #[test]
1336    fn test_iter_exact_size() {
1337        let mut list: SegList<i32> = SegList::new();
1338
1339        for i in 0..50 {
1340            list.push(i);
1341        }
1342
1343        // Test ExactSizeIterator on reverse iterator
1344        let iter = list.iter();
1345        assert_eq!(iter.len(), 50);
1346
1347        let mut iter = list.iter();
1348        assert_eq!(iter.len(), 50);
1349        assert_eq!(iter.next(), Some(&0));
1350        assert_eq!(iter.len(), 49);
1351        assert_eq!(iter.next(), Some(&1));
1352        assert_eq!(iter.len(), 48);
1353
1354        // Test ExactSizeIterator on mutable reverse iterator
1355        let mut iter_mut = list.iter_mut();
1356        assert_eq!(iter_mut.len(), 50);
1357        assert_eq!(iter_mut.next(), Some(&mut 0));
1358        assert_eq!(iter_mut.len(), 49);
1359    }
1360
1361    #[test]
1362    fn test_iter_rev_exact_size() {
1363        let mut list: SegList<i32> = SegList::new();
1364
1365        for i in 0..50 {
1366            list.push(i);
1367        }
1368
1369        // Test ExactSizeIterator on reverse iterator
1370        let iter = list.iter_rev();
1371        assert_eq!(iter.len(), 50);
1372
1373        let mut iter = list.iter_rev();
1374        assert_eq!(iter.len(), 50);
1375        assert_eq!(iter.next(), Some(&49));
1376        assert_eq!(iter.len(), 49);
1377        assert_eq!(iter.next(), Some(&48));
1378        assert_eq!(iter.len(), 48);
1379
1380        // Test ExactSizeIterator on mutable reverse iterator
1381        let mut iter_mut = list.iter_mut_rev();
1382        assert_eq!(iter_mut.len(), 50);
1383        assert_eq!(iter_mut.next(), Some(&mut 49));
1384        assert_eq!(iter_mut.len(), 49);
1385    }
1386
1387    #[test]
1388    fn test_into_iter_rev_single_segment() {
1389        // Test with small number of elements (single segment)
1390        let mut list: SegList<i32> = SegList::new();
1391
1392        for i in 0..10 {
1393            list.push(i);
1394        }
1395        let mut iter = list.into_iter_rev();
1396        assert_eq!(iter.len(), 10);
1397        // Test into_rev - should yield elements in LIFO order
1398        let mut drained: Vec<i32> = Vec::new();
1399        assert_eq!(iter.next(), Some(9));
1400        assert_eq!(iter.len(), 9);
1401        drained.push(9);
1402        let mut left: Vec<i32> = iter.collect();
1403        drained.append(&mut left);
1404        let expected: Vec<i32> = (0..10).rev().collect();
1405        assert_eq!(drained, expected);
1406    }
1407
1408    #[test]
1409    fn test_into_iter_multi_segment() {
1410        // Test with many elements (multiple segments)
1411        let mut list: SegList<i32> = SegList::new();
1412
1413        for i in 0..200i32 {
1414            list.push(i);
1415        }
1416        let mut iter = list.into_iter();
1417        assert_eq!(iter.len(), 200);
1418        for i in 0..200i32 {
1419            assert_eq!(iter.len(), 200 - (i as usize));
1420            assert_eq!(iter.next(), Some(i));
1421        }
1422        assert_eq!(iter.next(), None);
1423    }
1424
1425    #[test]
1426    fn test_into_iter_rev_multi_segment() {
1427        // Test with many elements (multiple segments)
1428        let mut list: SegList<i32> = SegList::new();
1429
1430        for i in 0..200i32 {
1431            list.push(i);
1432        }
1433        let mut iter = list.into_iter_rev();
1434        assert_eq!(iter.len(), 200);
1435        for i in 0..200i32 {
1436            assert_eq!(iter.len(), 200 - (i as usize));
1437            assert_eq!(iter.next(), Some(199 - i));
1438        }
1439        assert_eq!(iter.next(), None);
1440    }
1441
1442    #[test]
1443    fn test_into_iter_rev_empty() {
1444        let list: SegList<i32> = SegList::new();
1445        let iter = list.into_iter_rev();
1446        assert_eq!(iter.len(), 0);
1447        let drained: Vec<i32> = iter.collect();
1448        assert!(drained.is_empty());
1449    }
1450
1451    #[test]
1452    fn test_into_iter_rev_partial() {
1453        // Test partial consumption of into_iter_rev
1454        let mut list: SegList<i32> = SegList::new();
1455
1456        for i in 0..50 {
1457            list.push(i);
1458        }
1459
1460        // Only drain half
1461        let mut drain = list.into_iter_rev();
1462        let mut drained = Vec::new();
1463        for _ in 0..25 {
1464            if let Some(item) = drain.next() {
1465                drained.push(item);
1466            }
1467        }
1468        assert_eq!(drain.len(), 25);
1469        // Drop drain - remaining elements should be dropped properly
1470        drop(drain);
1471
1472        // Verify we got the last 25 elements in reverse order
1473        let expected: Vec<i32> = (25..50).rev().collect();
1474        assert_eq!(drained, expected);
1475    }
1476}