Skip to main content

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