mod slice;
mod sort;
pub use slice::{
Chunks, ChunksExact, RChunks, SegmentedSlice, SegmentedSliceMut, SliceIter, SliceIterMut,
Windows,
};
use std::alloc::{self, Layout};
use std::cmp::Ordering;
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
const MAX_SEGMENTS: usize = 64;
#[repr(C)]
pub struct SegmentedVec<T> {
write_ptr: *mut T,
segment_end: *mut T,
len: usize,
active_segment_index: usize,
segment_count: usize,
dynamic_segments: [*mut T; MAX_SEGMENTS],
_marker: PhantomData<T>,
}
impl<T> SegmentedVec<T> {
const MIN_NON_ZERO_CAP: usize = {
let size = std::mem::size_of::<T>();
if size == 1 {
8
} else if size <= 1024 {
4
} else {
1
}
};
const MIN_CAP_EXP: u32 = Self::MIN_NON_ZERO_CAP.trailing_zeros();
#[inline]
pub const fn new() -> Self {
Self {
dynamic_segments: [std::ptr::null_mut(); MAX_SEGMENTS],
segment_count: 0,
len: 0,
write_ptr: std::ptr::null_mut(),
segment_end: std::ptr::null_mut(),
active_segment_index: usize::MAX,
_marker: PhantomData,
}
}
#[inline]
pub const fn len(&self) -> usize {
self.len
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn capacity(&self) -> usize {
Self::compute_capacity(self.segment_count as u32)
}
#[inline]
pub fn push(&mut self, value: T) {
if self.write_ptr < self.segment_end {
unsafe {
std::ptr::write(self.write_ptr, value);
self.write_ptr = self.write_ptr.add(1);
}
self.len += 1;
return;
}
self.push_slow(value);
}
#[cold]
#[inline(never)]
fn push_slow(&mut self, value: T) {
self.active_segment_index = self.active_segment_index.wrapping_add(1);
if self.active_segment_index >= self.segment_count {
self.grow_once();
}
let idx = self.active_segment_index;
let base = unsafe { *self.dynamic_segments.get_unchecked(idx) };
let shelf_size = Self::MIN_NON_ZERO_CAP << idx;
unsafe {
std::ptr::write(base, value);
self.write_ptr = base.add(1);
self.segment_end = base.add(shelf_size);
}
self.len += 1;
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
if self.len == 0 {
return None;
}
let segment_base = unsafe {
*self
.dynamic_segments
.get_unchecked(self.active_segment_index)
};
if self.write_ptr > segment_base {
self.len -= 1;
unsafe {
self.write_ptr = self.write_ptr.sub(1);
Some(std::ptr::read(self.write_ptr))
}
} else {
self.pop_slow_path()
}
}
#[cold]
#[inline(never)]
fn pop_slow_path(&mut self) -> Option<T> {
self.active_segment_index -= 1;
let idx = self.active_segment_index;
let base = unsafe { *self.dynamic_segments.get_unchecked(idx) };
let capacity = Self::MIN_NON_ZERO_CAP << idx;
self.segment_end = unsafe { base.add(capacity) };
self.write_ptr = unsafe { self.segment_end.sub(1) };
self.len -= 1;
Some(unsafe { std::ptr::read(self.write_ptr) })
}
#[inline]
pub fn get(&self, index: usize) -> Option<&T> {
if index < self.len {
Some(unsafe { self.unchecked_at(index) })
} else {
None
}
}
#[inline]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index < self.len {
Some(unsafe { self.unchecked_at_mut(index) })
} else {
None
}
}
#[inline]
pub fn first(&self) -> Option<&T> {
if self.len == 0 {
None
} else {
Some(unsafe { &*self.dynamic_segments[0] })
}
}
#[inline]
pub fn first_mut(&mut self) -> Option<&mut T> {
if self.len == 0 {
None
} else {
Some(unsafe { &mut *self.dynamic_segments[0] })
}
}
#[inline]
pub fn last(&self) -> Option<&T> {
if self.len == 0 {
return None;
}
let segment_base = unsafe {
*self
.dynamic_segments
.get_unchecked(self.active_segment_index)
};
if self.write_ptr > segment_base {
Some(unsafe { &*self.write_ptr.sub(1) })
} else {
self.get(self.len - 1)
}
}
#[inline]
pub fn last_mut(&mut self) -> Option<&mut T> {
if self.len == 0 {
return None;
}
let segment_base = unsafe {
*self
.dynamic_segments
.get_unchecked(self.active_segment_index)
};
if self.write_ptr > segment_base {
Some(unsafe { &mut *self.write_ptr.sub(1) })
} else {
self.get_mut(self.len - 1)
}
}
#[inline]
pub fn contains(&self, x: &T) -> bool
where
T: PartialEq,
{
let mut remaining = self.len;
let mut segment_idx = 0;
while remaining > 0 {
let segment_capacity = Self::MIN_NON_ZERO_CAP << segment_idx;
let segment_len = segment_capacity.min(remaining);
let base = unsafe { *self.dynamic_segments.get_unchecked(segment_idx) };
let slice = unsafe { std::slice::from_raw_parts(base, segment_len) };
if slice.contains(x) {
return true;
}
segment_idx += 1;
remaining -= segment_len;
}
false
}
pub fn starts_with(&self, needle: &[T]) -> bool
where
T: PartialEq,
{
if needle.len() > self.len {
return false;
}
if needle.is_empty() {
return true;
}
let mut current_segment_capacity = Self::MIN_NON_ZERO_CAP;
let mut needle_cursor = 0;
let mut idx = 0;
while needle_cursor < needle.len() {
unsafe {
let segment_base = *self.dynamic_segments.get_unchecked(idx);
let remaining = needle.len() - needle_cursor;
let match_len = remaining.min(current_segment_capacity);
let haystack_slice = std::slice::from_raw_parts(segment_base, match_len);
let needle_slice = &needle[needle_cursor..needle_cursor + match_len];
if haystack_slice != needle_slice {
return false;
}
needle_cursor += match_len;
idx += 1;
current_segment_capacity <<= 1;
}
}
true
}
pub fn ends_with(&self, needle: &[T]) -> bool
where
T: PartialEq,
{
if needle.len() > self.len {
return false;
}
if needle.is_empty() {
return true;
}
let mut remaining = needle.len();
let mut idx = self.active_segment_index;
unsafe {
let segment_base = *self.dynamic_segments.get_unchecked(idx);
let segment_len = self.write_ptr.offset_from(segment_base) as usize;
let match_len = remaining.min(segment_len);
let haystack_start = self.write_ptr.sub(match_len);
let haystack_slice = std::slice::from_raw_parts(haystack_start, match_len);
let needle_start = remaining - match_len;
let needle_slice = &needle[needle_start..remaining];
if haystack_slice != needle_slice {
return false;
}
remaining -= match_len;
if remaining == 0 {
return true;
}
idx -= 1;
}
loop {
unsafe {
let segment_base = *self.dynamic_segments.get_unchecked(idx);
let segment_capacity = Self::MIN_NON_ZERO_CAP << idx;
let match_len = remaining.min(segment_capacity);
let haystack_start = segment_base.add(segment_capacity - match_len);
let haystack_slice = std::slice::from_raw_parts(haystack_start, match_len);
let needle_start = remaining - match_len;
let needle_slice = &needle[needle_start..remaining];
if haystack_slice != needle_slice {
return false;
}
remaining -= match_len;
if remaining == 0 {
return true;
}
idx -= 1;
}
}
}
pub fn binary_search(&self, x: &T) -> Result<usize, usize>
where
T: Ord,
{
self.binary_search_by(|p| p.cmp(x))
}
pub fn binary_search_by<F>(&self, mut f: F) -> Result<usize, usize>
where
F: FnMut(&T) -> Ordering,
{
if self.len == 0 {
return Err(0);
}
let active_capacity = Self::MIN_NON_ZERO_CAP << self.active_segment_index;
let segment_base = unsafe { self.segment_end.sub(active_capacity) };
let first_elem = unsafe { &*segment_base };
if f(first_elem) != Ordering::Greater {
unsafe {
let segment_len = self.write_ptr.offset_from(segment_base) as usize;
let slice = std::slice::from_raw_parts(segment_base, segment_len);
let offset = active_capacity - Self::MIN_NON_ZERO_CAP;
return match slice.binary_search_by(f) {
Ok(idx) => Ok(offset + idx),
Err(idx) => Err(offset + idx),
};
}
}
let mut idx = self.active_segment_index;
while idx > 0 {
idx -= 1;
unsafe {
let segment_base = *self.dynamic_segments.get_unchecked(idx);
if f(&*segment_base) != Ordering::Greater {
let capacity = Self::MIN_NON_ZERO_CAP << idx;
let slice = std::slice::from_raw_parts(segment_base, capacity);
let global_offset = capacity - Self::MIN_NON_ZERO_CAP;
return match slice.binary_search_by(f) {
Ok(i) => Ok(global_offset + i),
Err(i) => Err(global_offset + i),
};
}
}
}
Err(0)
}
pub fn binary_search_by_key<B, F>(&self, b: &B, mut f: F) -> Result<usize, usize>
where
F: FnMut(&T) -> B,
B: Ord,
{
self.binary_search_by(|k| f(k).cmp(b))
}
#[inline]
pub fn swap(&mut self, a: usize, b: usize) {
let ptr_b = &raw mut self[a];
let ptr_a = &raw mut self[b];
unsafe {
std::ptr::swap(ptr_b, ptr_a);
}
}
pub fn reverse(&mut self) {
if self.len < 2 {
return;
}
let mut remaining_total = self.len;
let mut f_segment_index = 0;
let mut f_segment_capacity = Self::MIN_NON_ZERO_CAP;
let mut f_segment_base = unsafe { *self.dynamic_segments.get_unchecked(0) };
let mut f_remaining = f_segment_capacity;
let mut b_segment_index = self.active_segment_index;
let mut b_segment_capacity = Self::MIN_NON_ZERO_CAP << b_segment_index;
let mut b_segment_base = unsafe { *self.dynamic_segments.get_unchecked(b_segment_index) };
let mut b_remaining = unsafe { self.write_ptr.offset_from(b_segment_base) as usize };
let mut b_segment_end = unsafe { self.write_ptr.sub(1) };
loop {
if f_segment_index == b_segment_index {
unsafe {
let slice = std::slice::from_raw_parts_mut(f_segment_base, remaining_total);
slice.reverse();
}
return;
}
let count = f_remaining.min(b_remaining);
unsafe {
self.swap_chunks_reversed_simd(f_segment_base, b_segment_end, count);
f_segment_base = f_segment_base.add(count);
b_segment_end = b_segment_end.sub(count);
}
remaining_total -= count * 2;
if remaining_total == 0 {
return;
}
f_remaining -= count;
if f_remaining == 0 {
f_segment_index += 1;
f_segment_capacity <<= 1;
f_remaining = f_segment_capacity;
unsafe {
f_segment_base = *self.dynamic_segments.get_unchecked(f_segment_index);
}
}
b_remaining -= count;
if b_remaining == 0 {
b_segment_index -= 1;
b_segment_capacity >>= 1;
b_remaining = b_segment_capacity;
unsafe {
b_segment_base = *self.dynamic_segments.get_unchecked(b_segment_index);
b_segment_end = b_segment_base.add(b_segment_capacity - 1);
}
}
}
}
#[inline(always)]
unsafe fn swap_chunks_reversed_simd(&mut self, base_a: *mut T, base_b: *mut T, count: usize) {
for i in 0..count {
std::ptr::swap(base_a.add(i), base_b.sub(i));
}
}
pub fn fill(&mut self, value: T)
where
T: Clone,
{
self.as_mut_slice().fill(value)
}
pub fn fill_with<F>(&mut self, f: F)
where
F: FnMut() -> T,
{
self.as_mut_slice().fill_with(f)
}
pub fn clear(&mut self) {
if self.len == 0 {
return;
}
if std::mem::needs_drop::<T>() {
let mut remaining = self.len;
for shelf in 0..self.segment_count {
let size = Self::shelf_size(shelf as u32);
let count = remaining.min(size);
let ptr = unsafe { *self.dynamic_segments.get_unchecked(shelf) };
unsafe { std::ptr::drop_in_place(std::ptr::slice_from_raw_parts_mut(ptr, count)) };
remaining -= count;
if remaining == 0 {
break;
}
}
}
self.len = 0;
self.write_ptr = std::ptr::null_mut();
self.segment_end = std::ptr::null_mut();
self.active_segment_index = usize::MAX;
}
pub fn truncate(&mut self, new_len: usize) {
if new_len >= self.len {
return;
}
if std::mem::needs_drop::<T>() {
let dynamic_new_len = new_len;
let dynamic_old_len = self.len;
if dynamic_new_len < dynamic_old_len {
let mut pos = 0usize;
for shelf in 0..self.segment_count {
let size = Self::shelf_size(shelf as u32);
let seg_end = pos + size;
let drop_start = dynamic_new_len.max(pos);
let drop_end = dynamic_old_len.min(seg_end);
if drop_start < drop_end {
let offset = drop_start - pos;
let count = drop_end - drop_start;
let ptr =
unsafe { (*self.dynamic_segments.get_unchecked(shelf)).add(offset) };
unsafe {
std::ptr::drop_in_place(std::ptr::slice_from_raw_parts_mut(ptr, count))
};
}
pos = seg_end;
if pos >= dynamic_old_len {
break;
}
}
}
}
self.len = new_len;
if new_len > 0 {
let biased = new_len + Self::MIN_NON_ZERO_CAP;
let msb = biased.ilog2();
let idx = (msb - Self::MIN_CAP_EXP) as usize;
self.active_segment_index = idx;
let capacity = 1usize << msb;
let offset = biased ^ capacity;
unsafe {
let base = *self.dynamic_segments.get_unchecked(idx);
self.write_ptr = base.add(offset);
self.segment_end = base.add(capacity);
}
} else {
self.write_ptr = std::ptr::null_mut();
self.segment_end = std::ptr::null_mut();
self.active_segment_index = usize::MAX;
}
}
pub fn reserve(&mut self, additional: usize) {
self.grow_capacity(self.len + additional);
if self.write_ptr.is_null() {
unsafe {
let base = *self.dynamic_segments.get_unchecked(0);
self.write_ptr = base;
self.segment_end = base.add(Self::MIN_NON_ZERO_CAP);
self.active_segment_index = 0;
}
}
}
pub fn shrink_to_fit(&mut self) {
self.shrink_capacity(self.len);
}
#[inline]
pub fn iter(&self) -> Iter<'_, T> {
Iter {
vec: self,
ptr: std::ptr::null(),
segment_end: std::ptr::null(),
index: 0,
shelf_index: 0,
}
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
IterMut {
vec: self,
ptr: std::ptr::null_mut(),
segment_end: std::ptr::null_mut(),
index: 0,
shelf_index: 0,
}
}
#[inline]
pub fn as_slice(&self) -> SegmentedSlice<'_, T> {
SegmentedSlice::new(self)
}
#[inline]
pub fn as_mut_slice(&mut self) -> SegmentedSliceMut<'_, T> {
SegmentedSliceMut::new(self)
}
#[inline]
pub fn slice(&self, range: std::ops::Range<usize>) -> SegmentedSlice<'_, T> {
assert!(range.start <= range.end && range.end <= self.len);
SegmentedSlice::from_range(self, range.start, range.end)
}
#[inline]
pub fn slice_mut(&mut self, range: std::ops::Range<usize>) -> SegmentedSliceMut<'_, T> {
assert!(range.start <= range.end && range.end <= self.len);
SegmentedSliceMut::from_range(self, range.start, range.end)
}
pub fn extend_from_slice(&mut self, other: &[T])
where
T: Clone,
{
if other.is_empty() {
return;
}
self.reserve(other.len());
let mut src = other;
while !src.is_empty() {
let (shelf, box_idx, remaining) = Self::location_with_capacity(self.len);
let to_copy = src.len().min(remaining);
let dest = unsafe { (*self.dynamic_segments.get_unchecked(shelf)).add(box_idx) };
for (i, item) in src.iter().take(to_copy).enumerate() {
unsafe { std::ptr::write(dest.add(i), item.clone()) };
}
self.len += to_copy;
src = &src[to_copy..];
}
if self.len > 0 {
let biased = self.len + Self::MIN_NON_ZERO_CAP;
let msb = biased.ilog2();
let idx = (msb - Self::MIN_CAP_EXP) as usize;
self.active_segment_index = idx;
let capacity = 1usize << msb;
let offset = biased ^ capacity;
unsafe {
let base = *self.dynamic_segments.get_unchecked(idx);
self.write_ptr = base.add(offset);
self.segment_end = base.add(capacity);
}
}
}
pub fn extend_from_copy_slice(&mut self, other: &[T])
where
T: Copy,
{
if other.is_empty() {
return;
}
self.reserve(other.len());
let mut src = other;
while !src.is_empty() {
let (shelf, box_idx, remaining) = Self::location_with_capacity(self.len);
let to_copy = src.len().min(remaining);
unsafe {
let dest = (*self.dynamic_segments.get_unchecked(shelf)).add(box_idx);
std::ptr::copy_nonoverlapping(src.as_ptr(), dest, to_copy);
};
self.len += to_copy;
src = &src[to_copy..];
}
if self.len > 0 {
let biased = self.len + Self::MIN_NON_ZERO_CAP;
let msb = biased.ilog2();
let idx = (msb - Self::MIN_CAP_EXP) as usize;
self.active_segment_index = idx;
let capacity = 1usize << msb;
let offset = biased ^ capacity;
unsafe {
let base = *self.dynamic_segments.get_unchecked(idx);
self.write_ptr = base.add(offset);
self.segment_end = base.add(capacity);
}
}
}
#[inline]
pub fn sort(&mut self)
where
T: Ord,
{
self.as_mut_slice().sort();
}
pub fn sort_by<F>(&mut self, compare: F)
where
F: FnMut(&T, &T) -> Ordering,
{
self.as_mut_slice().sort_by(compare);
}
#[inline]
pub fn sort_by_key<K, F>(&mut self, f: F)
where
F: FnMut(&T) -> K,
K: Ord,
{
self.as_mut_slice().sort_by_key(f);
}
#[inline]
pub fn sort_unstable(&mut self)
where
T: Ord,
{
self.as_mut_slice().sort_unstable();
}
pub fn sort_unstable_by<F>(&mut self, compare: F)
where
F: FnMut(&T, &T) -> Ordering,
{
self.as_mut_slice().sort_unstable_by(compare);
}
#[inline]
pub fn sort_unstable_by_key<K, F>(&mut self, f: F)
where
F: FnMut(&T) -> K,
K: Ord,
{
self.as_mut_slice().sort_unstable_by_key(f);
}
pub fn is_sorted(&self) -> bool
where
T: PartialOrd,
{
self.as_slice().is_sorted()
}
pub fn is_sorted_by<F>(&self, compare: F) -> bool
where
F: FnMut(&T, &T) -> bool,
{
self.as_slice().is_sorted_by(compare)
}
pub fn is_sorted_by_key<K, F>(&self, f: F) -> bool
where
F: FnMut(&T) -> K,
K: PartialOrd,
{
self.as_slice().is_sorted_by_key(f)
}
pub fn partition_point<P>(&self, pred: P) -> usize
where
P: FnMut(&T) -> bool,
{
self.as_slice().partition_point(pred)
}
pub fn rotate_left(&mut self, mid: usize) {
self.as_mut_slice().rotate_left(mid);
}
pub fn rotate_right(&mut self, k: usize) {
self.as_mut_slice().rotate_right(k);
}
pub fn with_capacity(capacity: usize) -> Self {
let mut vec = Self::new();
vec.reserve(capacity);
vec
}
pub fn insert(&mut self, index: usize, element: T) {
assert!(index <= self.len);
self.push(element);
if index < self.len - 1 {
for i in (index..self.len - 1).rev() {
unsafe {
let ptr_a = self.unchecked_at_mut(i) as *mut T;
let ptr_b = self.unchecked_at_mut(i + 1) as *mut T;
std::ptr::swap(ptr_a, ptr_b);
}
}
}
}
pub fn remove(&mut self, index: usize) -> T {
assert!(index < self.len);
for i in index..self.len - 1 {
unsafe {
let ptr_a = self.unchecked_at_mut(i) as *mut T;
let ptr_b = self.unchecked_at_mut(i + 1) as *mut T;
std::ptr::swap(ptr_a, ptr_b);
}
}
self.pop().unwrap()
}
pub fn swap_remove(&mut self, index: usize) -> T {
assert!(index < self.len);
let last_index = self.len - 1;
if index != last_index {
unsafe {
let ptr_a = self.unchecked_at_mut(index) as *mut T;
let ptr_b = self.unchecked_at_mut(last_index) as *mut T;
std::ptr::swap(ptr_a, ptr_b);
}
}
self.pop().unwrap()
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
let mut i = 0;
while i < self.len {
if f(unsafe { self.unchecked_at(i) }) {
i += 1;
} else {
self.remove(i);
}
}
}
pub fn retain_mut<F>(&mut self, mut f: F)
where
F: FnMut(&mut T) -> bool,
{
let mut i = 0;
while i < self.len {
if f(unsafe { self.unchecked_at_mut(i) }) {
i += 1;
} else {
self.remove(i);
}
}
}
pub fn dedup(&mut self)
where
T: PartialEq,
{
self.dedup_by(|a, b| a == b);
}
pub fn dedup_by<F>(&mut self, mut same_bucket: F)
where
F: FnMut(&mut T, &mut T) -> bool,
{
if self.len <= 1 {
return;
}
let mut write = 1;
for read in 1..self.len {
let should_keep = unsafe {
let prev_ptr = self.unchecked_at_mut(write - 1) as *mut T;
let curr_ptr = self.unchecked_at_mut(read) as *mut T;
!same_bucket(&mut *prev_ptr, &mut *curr_ptr)
};
if should_keep {
if read != write {
unsafe {
let ptr_src = self.unchecked_at_mut(read) as *mut T;
let ptr_dst = self.unchecked_at_mut(write) as *mut T;
std::ptr::swap(ptr_dst, ptr_src);
}
}
write += 1;
} else {
unsafe {
std::ptr::drop_in_place(self.unchecked_at_mut(read));
}
}
}
self.len = write;
}
pub fn dedup_by_key<K, F>(&mut self, mut key: F)
where
F: FnMut(&mut T) -> K,
K: PartialEq,
{
self.dedup_by(|a, b| key(a) == key(b));
}
pub fn resize(&mut self, new_len: usize, value: T)
where
T: Clone,
{
if new_len > self.len {
self.reserve(new_len - self.len);
while self.len < new_len {
self.push(value.clone());
}
} else {
self.truncate(new_len);
}
}
pub fn resize_with<F>(&mut self, new_len: usize, mut f: F)
where
F: FnMut() -> T,
{
if new_len > self.len {
self.reserve(new_len - self.len);
while self.len < new_len {
self.push(f());
}
} else {
self.truncate(new_len);
}
}
pub fn append(&mut self, other: &mut Self) {
let other_len = other.len;
self.reserve(other_len);
let start = self.len;
while let Some(item) = other.pop() {
self.push(item);
}
let mut left = start;
let mut right = self.len;
while left < right {
right -= 1;
if left < right {
unsafe {
let ptr_a = self.unchecked_at_mut(left) as *mut T;
let ptr_b = self.unchecked_at_mut(right) as *mut T;
std::ptr::swap(ptr_a, ptr_b);
}
left += 1;
}
}
}
pub fn split_off(&mut self, at: usize) -> Self {
assert!(at <= self.len);
let mut other = Self::new();
other.reserve(self.len - at);
for i in at..self.len {
other.push(unsafe { self.unchecked_read(i) });
}
self.len = at;
other
}
pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> {
self.as_slice().chunks(chunk_size)
}
pub fn windows(&self, size: usize) -> Windows<'_, T> {
self.as_slice().windows(size)
}
pub fn rchunks(&self, chunk_size: usize) -> RChunks<'_, T> {
self.as_slice().rchunks(chunk_size)
}
pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> {
self.as_slice().chunks_exact(chunk_size)
}
pub fn drain(&mut self, range: std::ops::Range<usize>) -> Drain<'_, T> {
assert!(range.start <= range.end && range.end <= self.len);
Drain {
vec: self,
range_start: range.start,
range_end: range.end,
index: range.start,
}
}
pub fn to_vec(&self) -> Vec<T>
where
T: Clone,
{
self.as_slice().to_vec()
}
#[inline]
fn shelf_count(box_count: usize) -> u32 {
if box_count == 0 {
return 0;
}
let val = box_count + Self::MIN_NON_ZERO_CAP;
val.next_power_of_two().trailing_zeros() - Self::MIN_CAP_EXP
}
#[inline]
fn shelf_size(shelf_index: u32) -> usize {
Self::MIN_NON_ZERO_CAP << shelf_index
}
#[inline]
fn location(list_index: usize) -> (usize, usize) {
let biased = list_index + Self::MIN_NON_ZERO_CAP;
let msb = biased.ilog2();
let shelf = msb - Self::MIN_CAP_EXP;
let box_idx = biased ^ (1usize << msb);
(shelf as usize, box_idx)
}
#[inline]
fn location_with_capacity(list_index: usize) -> (usize, usize, usize) {
let biased = list_index + Self::MIN_NON_ZERO_CAP;
let msb = biased.ilog2();
let shelf = msb - Self::MIN_CAP_EXP;
let box_idx = biased ^ (1usize << msb);
let segment_remaining = (2usize << msb) - biased;
(shelf as usize, box_idx, segment_remaining)
}
#[inline]
pub(crate) unsafe fn unchecked_at(&self, index: usize) -> &T {
unsafe {
let (shelf, box_idx) = Self::location(index);
&*(*self.dynamic_segments.get_unchecked(shelf)).add(box_idx)
}
}
#[inline]
pub(crate) unsafe fn unchecked_at_mut(&mut self, index: usize) -> &mut T {
unsafe {
let (shelf, box_idx) = Self::location(index);
&mut *(*self.dynamic_segments.get_unchecked(shelf)).add(box_idx)
}
}
#[inline]
unsafe fn unchecked_read(&self, index: usize) -> T {
unsafe {
let (shelf, box_idx) = Self::location(index);
std::ptr::read((*self.dynamic_segments.get_unchecked(shelf)).add(box_idx))
}
}
fn grow_once(&mut self) {
assert!(
self.segment_count < MAX_SEGMENTS,
"Maximum segment count exceeded"
);
let size = Self::shelf_size(self.segment_count as u32);
let layout = Layout::array::<T>(size).expect("Layout overflow");
let ptr = if layout.size() == 0 {
std::ptr::dangling_mut::<T>()
} else {
let ptr = unsafe { alloc::alloc(layout) };
if ptr.is_null() {
panic!("Allocation failed");
}
ptr as *mut T
};
self.dynamic_segments[self.segment_count] = ptr;
self.segment_count += 1;
}
fn grow_capacity(&mut self, new_capacity: usize) {
let new_shelf_count = Self::shelf_count(new_capacity) as usize;
let old_shelf_count = self.segment_count;
if new_shelf_count > old_shelf_count {
assert!(
new_shelf_count <= MAX_SEGMENTS,
"Maximum segment count exceeded"
);
for i in old_shelf_count..new_shelf_count {
let size = Self::shelf_size(i as u32);
let layout = Layout::array::<T>(size).expect("Layout overflow");
let ptr = if layout.size() == 0 {
std::ptr::dangling_mut::<T>()
} else {
let ptr = unsafe { alloc::alloc(layout) };
if ptr.is_null() {
panic!("Allocation failed");
}
ptr as *mut T
};
self.dynamic_segments[i] = ptr;
}
self.segment_count = new_shelf_count;
}
}
#[inline]
fn compute_capacity(shelf_count: u32) -> usize {
(Self::MIN_NON_ZERO_CAP << shelf_count) - Self::MIN_NON_ZERO_CAP
}
fn shrink_capacity(&mut self, new_capacity: usize) {
let new_shelf_count = Self::shelf_count(new_capacity);
let old_shelf_count = self.segment_count as u32;
if new_shelf_count < old_shelf_count {
self.free_shelves(old_shelf_count, new_shelf_count);
self.segment_count = new_shelf_count as usize;
}
}
fn free_shelves(&mut self, from_count: u32, to_count: u32) {
for i in (to_count..from_count).rev() {
let size = Self::shelf_size(i);
let layout = Layout::array::<T>(size).expect("Layout overflow");
if layout.size() > 0 {
unsafe {
alloc::dealloc(self.dynamic_segments[i as usize] as *mut u8, layout);
}
}
self.dynamic_segments[i as usize] = std::ptr::null_mut();
}
}
}
impl<T> Drop for SegmentedVec<T> {
fn drop(&mut self) {
self.clear();
self.free_shelves(self.segment_count as u32, 0);
}
}
impl<T> sort::IndexedAccess<T> for SegmentedVec<T> {
#[inline]
fn get_ref(&self, index: usize) -> &T {
debug_assert!(index < self.len);
unsafe { self.unchecked_at(index) }
}
#[inline]
fn get_ptr(&self, index: usize) -> *const T {
debug_assert!(index < self.len);
let (shelf, box_idx) = Self::location(index);
unsafe { (*self.dynamic_segments.get_unchecked(shelf)).add(box_idx) }
}
#[inline]
fn get_ptr_mut(&mut self, index: usize) -> *mut T {
debug_assert!(index < self.len);
let (shelf, box_idx) = Self::location(index);
unsafe { (*self.dynamic_segments.get_unchecked(shelf)).add(box_idx) }
}
#[inline]
fn swap(&mut self, a: usize, b: usize) {
if a == b {
return;
}
debug_assert!(a < self.len && b < self.len);
unsafe {
let ptr_a = self.get_ptr_mut(a);
let ptr_b = self.get_ptr_mut(b);
std::ptr::swap(ptr_a, ptr_b);
}
}
}
impl<T> Default for SegmentedVec<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Index<usize> for SegmentedVec<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
self.get(index).expect("index out of bounds")
}
}
impl<T> IndexMut<usize> for SegmentedVec<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.get_mut(index).expect("index out of bounds")
}
}
impl<T: Clone> Clone for SegmentedVec<T> {
fn clone(&self) -> Self {
if self.len == 0 {
return Self::new();
}
let mut new_vec = Self::new();
new_vec.reserve(self.len);
let mut remaining = self.len;
for shelf in 0..self.segment_count {
let size = Self::shelf_size(shelf as u32);
let count = remaining.min(size);
let src = unsafe { *self.dynamic_segments.get_unchecked(shelf) };
let dst = unsafe { *new_vec.dynamic_segments.get_unchecked(shelf) };
for i in 0..count {
unsafe { std::ptr::write(dst.add(i), (*src.add(i)).clone()) };
}
new_vec.len += count;
remaining -= count;
if remaining == 0 {
break;
}
}
if new_vec.len > 0 {
let biased = new_vec.len + Self::MIN_NON_ZERO_CAP;
let msb = biased.ilog2();
let idx = (msb - Self::MIN_CAP_EXP) as usize;
new_vec.active_segment_index = idx;
let capacity = 1usize << msb;
let offset = biased ^ capacity;
unsafe {
let base = *new_vec.dynamic_segments.get_unchecked(idx);
new_vec.write_ptr = base.add(offset);
new_vec.segment_end = base.add(capacity);
}
}
new_vec
}
}
impl<T: std::fmt::Debug> std::fmt::Debug for SegmentedVec<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<T: PartialEq> PartialEq for SegmentedVec<T> {
fn eq(&self, other: &Self) -> bool {
if self.len != other.len {
return false;
}
for i in 0..self.len {
if unsafe { self.unchecked_at(i) } != unsafe { other.unchecked_at(i) } {
return false;
}
}
true
}
}
impl<T: Eq> Eq for SegmentedVec<T> {}
impl<T> FromIterator<T> for SegmentedVec<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let iter = iter.into_iter();
let (lower, _) = iter.size_hint();
let mut vec = Self::new();
vec.reserve(lower);
for item in iter {
vec.push(item);
}
vec
}
}
impl<T> Extend<T> for SegmentedVec<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
let iter = iter.into_iter();
let (lower, _) = iter.size_hint();
self.reserve(lower);
for item in iter {
self.push(item);
}
}
}
pub struct Iter<'a, T> {
vec: &'a SegmentedVec<T>,
ptr: *const T,
segment_end: *const T,
index: usize,
shelf_index: u32,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.ptr < self.segment_end {
let result = unsafe { &*self.ptr };
self.ptr = unsafe { self.ptr.add(1) };
self.index += 1;
return Some(result);
}
self.next_segment()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.vec.len.saturating_sub(self.index);
(remaining, Some(remaining))
}
}
impl<'a, T> Iter<'a, T> {
#[inline]
fn next_segment(&mut self) -> Option<&'a T> {
if self.index >= self.vec.len {
return None;
}
let shelf_idx = self.shelf_index as usize;
let shelf_size = SegmentedVec::<T>::shelf_size(self.shelf_index);
let ptr = self.vec.dynamic_segments[shelf_idx];
let segment_len = shelf_size.min(self.vec.len - self.index);
self.ptr = ptr;
self.segment_end = unsafe { ptr.add(segment_len) };
self.shelf_index += 1;
let result = unsafe { &*self.ptr };
self.ptr = unsafe { self.ptr.add(1) };
self.index += 1;
Some(result)
}
}
impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
pub struct IterMut<'a, T> {
vec: &'a mut SegmentedVec<T>,
ptr: *mut T,
segment_end: *mut T,
index: usize,
shelf_index: u32,
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.ptr < self.segment_end {
let result = self.ptr;
self.ptr = unsafe { self.ptr.add(1) };
self.index += 1;
return Some(unsafe { &mut *result });
}
self.next_segment()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.vec.len.saturating_sub(self.index);
(remaining, Some(remaining))
}
}
impl<'a, T> IterMut<'a, T> {
#[inline]
fn next_segment(&mut self) -> Option<&'a mut T> {
if self.index >= self.vec.len {
return None;
}
let shelf_idx = self.shelf_index as usize;
let shelf_size = SegmentedVec::<T>::shelf_size(self.shelf_index);
let ptr = self.vec.dynamic_segments[shelf_idx];
let segment_len = shelf_size.min(self.vec.len - self.index);
self.ptr = ptr;
self.segment_end = unsafe { ptr.add(segment_len) };
self.shelf_index += 1;
let result = self.ptr;
self.ptr = unsafe { self.ptr.add(1) };
self.index += 1;
Some(unsafe { &mut *result })
}
}
impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
impl<T> IntoIterator for SegmentedVec<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
vec: self,
index: 0,
}
}
}
impl<'a, T> IntoIterator for &'a SegmentedVec<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T> IntoIterator for &'a mut SegmentedVec<T> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
pub struct IntoIter<T> {
vec: SegmentedVec<T>,
index: usize,
}
impl<T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.vec.len {
return None;
}
let value = unsafe { self.vec.unchecked_read(self.index) };
self.index += 1;
Some(value)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.vec.len - self.index;
(remaining, Some(remaining))
}
}
impl<T> ExactSizeIterator for IntoIter<T> {}
impl<T> Drop for IntoIter<T> {
fn drop(&mut self) {
for i in self.index..self.vec.len {
unsafe {
std::ptr::drop_in_place(self.vec.unchecked_at_mut(i));
}
}
self.vec.len = 0;
}
}
pub struct Drain<'a, T> {
vec: &'a mut SegmentedVec<T>,
range_start: usize,
range_end: usize,
index: usize,
}
impl<'a, T> Iterator for Drain<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.range_end {
None
} else {
let value = unsafe { std::ptr::read(self.vec.unchecked_at(self.index)) };
self.index += 1;
Some(value)
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.range_end - self.index;
(remaining, Some(remaining))
}
}
impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.index >= self.range_end {
None
} else {
self.range_end -= 1;
Some(unsafe { std::ptr::read(self.vec.unchecked_at(self.range_end)) })
}
}
}
impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
impl<'a, T> Drop for Drain<'a, T> {
fn drop(&mut self) {
for i in self.index..self.range_end {
unsafe {
std::ptr::drop_in_place(self.vec.unchecked_at_mut(i));
}
}
let original_range_end = self.range_end;
let original_len = self.vec.len;
let drain_count = original_range_end - self.range_start;
for i in 0..(original_len - original_range_end) {
unsafe {
let src = self.vec.unchecked_at(original_range_end + i) as *const T;
let dst = self.vec.unchecked_at_mut(self.range_start + i) as *mut T;
std::ptr::copy_nonoverlapping(src, dst, 1);
}
}
self.vec.len = original_len - drain_count;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_empty() {
let vec: SegmentedVec<i32> = SegmentedVec::new();
assert!(vec.is_empty());
assert_eq!(vec.len(), 0);
}
#[test]
fn test_push_pop() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.push(1);
vec.push(2);
vec.push(3);
assert_eq!(vec.len(), 3);
assert_eq!(vec.pop(), Some(3));
assert_eq!(vec.pop(), Some(2));
assert_eq!(vec.pop(), Some(1));
assert_eq!(vec.pop(), None);
}
#[test]
fn test_get() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.push(10);
vec.push(20);
vec.push(30);
assert_eq!(vec.get(0), Some(&10));
assert_eq!(vec.get(1), Some(&20));
assert_eq!(vec.get(2), Some(&30));
assert_eq!(vec.get(3), None);
}
#[test]
fn test_index() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.push(10);
vec.push(20);
assert_eq!(vec[0], 10);
assert_eq!(vec[1], 20);
vec[0] = 100;
assert_eq!(vec[0], 100);
}
#[test]
fn test_stable_pointers() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.push(1);
let ptr = &vec[0] as *const i32;
for i in 2..1000 {
vec.push(i);
}
assert_eq!(unsafe { *ptr }, 1);
}
#[test]
fn test_iter() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
for i in 0..100 {
vec.push(i);
}
let collected: Vec<i32> = vec.iter().copied().collect();
let expected: Vec<i32> = (0..100).collect();
assert_eq!(collected, expected);
}
#[test]
fn test_iter_mut() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
for i in 0..10 {
vec.push(i);
}
for item in vec.iter_mut() {
*item *= 2;
}
let collected: Vec<i32> = vec.iter().copied().collect();
let expected: Vec<i32> = (0..10).map(|x| x * 2).collect();
assert_eq!(collected, expected);
}
#[test]
fn test_into_iter() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
for i in 0..10 {
vec.push(i);
}
let collected: Vec<i32> = vec.into_iter().collect();
let expected: Vec<i32> = (0..10).collect();
assert_eq!(collected, expected);
}
#[test]
fn test_from_iter() {
let vec: SegmentedVec<i32> = (0..10).collect();
assert_eq!(vec.len(), 10);
for i in 0..10 {
assert_eq!(vec[i], i as i32);
}
}
#[test]
fn test_extend() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..5);
vec.extend(5..10);
assert_eq!(vec.len(), 10);
for i in 0..10 {
assert_eq!(vec[i], i as i32);
}
}
#[test]
fn test_clear() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
vec.clear();
assert!(vec.is_empty());
assert_eq!(vec.len(), 0);
}
#[test]
fn test_truncate() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
vec.truncate(5);
assert_eq!(vec.len(), 5);
for i in 0..5 {
assert_eq!(vec[i], i as i32);
}
}
#[test]
fn test_clone() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
let vec2 = vec.clone();
assert_eq!(vec, vec2);
}
#[test]
fn test_debug() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..3);
let debug_str = format!("{:?}", vec);
assert_eq!(debug_str, "[0, 1, 2]");
}
#[test]
fn test_first_last() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
assert_eq!(vec.first(), None);
assert_eq!(vec.last(), None);
vec.push(1);
assert_eq!(vec.first(), Some(&1));
assert_eq!(vec.last(), Some(&1));
vec.push(2);
vec.push(3);
assert_eq!(vec.first(), Some(&1));
assert_eq!(vec.last(), Some(&3));
}
#[test]
fn test_drop_elements() {
use std::cell::Cell;
use std::rc::Rc;
let drop_count = Rc::new(Cell::new(0));
struct DropCounter {
counter: Rc<Cell<i32>>,
}
impl Drop for DropCounter {
fn drop(&mut self) {
self.counter.set(self.counter.get() + 1);
}
}
{
let mut vec: SegmentedVec<DropCounter> = SegmentedVec::new();
for _ in 0..10 {
vec.push(DropCounter {
counter: Rc::clone(&drop_count),
});
}
}
assert_eq!(drop_count.get(), 10);
}
#[test]
fn test_shrink_to_fit() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..100);
vec.truncate(5);
vec.shrink_to_fit();
assert_eq!(vec.len(), 5);
for i in 0..5 {
assert_eq!(vec[i], i as i32);
}
}
#[test]
fn test_sort() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend([5, 2, 8, 1, 9, 3, 7, 4, 6, 0]);
vec.sort();
let result: Vec<i32> = vec.iter().copied().collect();
assert_eq!(result, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
}
#[test]
fn test_sort_empty() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.sort();
assert!(vec.is_empty());
}
#[test]
fn test_sort_single() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.push(42);
vec.sort();
assert_eq!(vec[0], 42);
}
#[test]
fn test_sort_already_sorted() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
vec.sort();
let result: Vec<i32> = vec.iter().copied().collect();
assert_eq!(result, (0..10).collect::<Vec<_>>());
}
#[test]
fn test_sort_reverse_sorted() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend((0..10).rev());
vec.sort();
let result: Vec<i32> = vec.iter().copied().collect();
assert_eq!(result, (0..10).collect::<Vec<_>>());
}
#[test]
fn test_sort_by() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend([5, 2, 8, 1, 9, 3, 7, 4, 6, 0]);
vec.sort_by(|a, b| b.cmp(a)); let result: Vec<i32> = vec.iter().copied().collect();
assert_eq!(result, vec![9, 8, 7, 6, 5, 4, 3, 2, 1, 0]);
}
#[test]
fn test_sort_by_key() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend([-5, 2, -8, 1, -9, 3, -7, 4, -6, 0]);
vec.sort_by_key(|k| k.abs());
let result: Vec<i32> = vec.iter().copied().collect();
assert_eq!(result, vec![0, 1, 2, 3, 4, -5, -6, -7, -8, -9]);
}
#[test]
fn test_sort_stable() {
#[derive(Debug, Clone, Eq, PartialEq)]
struct Item {
key: i32,
order: usize,
}
let mut vec: SegmentedVec<Item> = SegmentedVec::new();
vec.push(Item { key: 1, order: 0 });
vec.push(Item { key: 2, order: 1 });
vec.push(Item { key: 1, order: 2 });
vec.push(Item { key: 2, order: 3 });
vec.push(Item { key: 1, order: 4 });
vec.sort_by_key(|item| item.key);
assert_eq!(vec[0], Item { key: 1, order: 0 });
assert_eq!(vec[1], Item { key: 1, order: 2 });
assert_eq!(vec[2], Item { key: 1, order: 4 });
assert_eq!(vec[3], Item { key: 2, order: 1 });
assert_eq!(vec[4], Item { key: 2, order: 3 });
}
#[test]
fn test_sort_unstable() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend([5, 2, 8, 1, 9, 3, 7, 4, 6, 0]);
vec.sort_unstable();
let result: Vec<i32> = vec.iter().copied().collect();
assert_eq!(result, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
}
#[test]
fn test_sort_unstable_by() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend([5, 2, 8, 1, 9, 3, 7, 4, 6, 0]);
vec.sort_unstable_by(|a, b| b.cmp(a)); let result: Vec<i32> = vec.iter().copied().collect();
assert_eq!(result, vec![9, 8, 7, 6, 5, 4, 3, 2, 1, 0]);
}
#[test]
fn test_sort_unstable_by_key() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend([-5, 2, -8, 1, -9, 3, -7, 4, -6, 0]);
vec.sort_unstable_by_key(|k| k.abs());
let result: Vec<i32> = vec.iter().copied().collect();
for i in 1..result.len() {
assert!(result[i - 1].abs() <= result[i].abs());
}
}
#[test]
fn test_sort_large() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend((0..1000).rev());
vec.sort();
for i in 0..1000 {
assert_eq!(vec[i], i as i32);
}
}
#[test]
fn test_sort_unstable_large() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend((0..1000).rev());
vec.sort_unstable();
for i in 0..1000 {
assert_eq!(vec[i], i as i32);
}
}
#[test]
fn test_sort_pointers_remain_stable_after_sort() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend([5, 2, 8, 1, 9]);
let ptr = &vec[0] as *const i32;
vec.sort();
assert_eq!(unsafe { *ptr }, 1); }
#[test]
fn test_as_slice() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
let slice = vec.as_slice();
assert_eq!(slice.len(), 10);
assert_eq!(slice[0], 0);
assert_eq!(slice[9], 9);
}
#[test]
fn test_as_mut_slice() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
{
let mut slice = vec.as_mut_slice();
slice[0] = 100;
slice[9] = 200;
}
assert_eq!(vec[0], 100);
assert_eq!(vec[9], 200);
}
#[test]
fn test_slice_range() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
let slice = vec.slice(2..5);
assert_eq!(slice.len(), 3);
assert_eq!(slice[0], 2);
assert_eq!(slice[1], 3);
assert_eq!(slice[2], 4);
}
#[test]
fn test_slice_mut_range() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
{
let mut slice = vec.slice_mut(2..5);
slice[0] = 100;
slice[2] = 200;
}
assert_eq!(vec[2], 100);
assert_eq!(vec[4], 200);
}
#[test]
fn test_slice_first_last() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
let slice = vec.as_slice();
assert_eq!(slice.first(), Some(&0));
assert_eq!(slice.last(), Some(&9));
}
#[test]
fn test_slice_iter() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
let slice = vec.as_slice();
let collected: Vec<i32> = slice.iter().copied().collect();
assert_eq!(collected, (0..10).collect::<Vec<_>>());
}
#[test]
fn test_slice_iter_rev() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
let slice = vec.as_slice();
let collected: Vec<i32> = slice.iter().rev().copied().collect();
assert_eq!(collected, (0..10).rev().collect::<Vec<_>>());
}
#[test]
fn test_slice_contains() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
let slice = vec.as_slice();
assert!(slice.contains(&5));
assert!(!slice.contains(&100));
}
#[test]
fn test_slice_binary_search() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..100);
let slice = vec.as_slice();
assert_eq!(slice.binary_search(&50), Ok(50));
assert_eq!(slice.binary_search(&0), Ok(0));
assert_eq!(slice.binary_search(&99), Ok(99));
assert_eq!(slice.binary_search(&100), Err(100));
}
#[test]
fn test_slice_split_at() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
let slice = vec.as_slice();
let (left, right) = slice.split_at(5);
assert_eq!(left.len(), 5);
assert_eq!(right.len(), 5);
assert_eq!(left[0], 0);
assert_eq!(right[0], 5);
}
#[test]
fn test_slice_to_vec() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
let slice = vec.as_slice();
let converted = slice.to_vec();
assert_eq!(converted, (0..10).collect::<Vec<_>>());
}
#[test]
fn test_slice_mut_sort() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend([5, 3, 1, 4, 2, 8, 7, 6, 0, 9]);
{
let mut slice = vec.slice_mut(2..8);
slice.sort();
}
let result: Vec<i32> = vec.iter().copied().collect();
assert_eq!(result, vec![5, 3, 1, 2, 4, 6, 7, 8, 0, 9]);
}
#[test]
fn test_slice_mut_reverse() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
{
let mut slice = vec.slice_mut(2..8);
slice.reverse();
}
let result: Vec<i32> = vec.iter().copied().collect();
assert_eq!(result, vec![0, 1, 7, 6, 5, 4, 3, 2, 8, 9]);
}
#[test]
fn test_slice_mut_fill() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
{
let mut slice = vec.slice_mut(2..5);
slice.fill(99);
}
let result: Vec<i32> = vec.iter().copied().collect();
assert_eq!(result, vec![0, 1, 99, 99, 99, 5, 6, 7, 8, 9]);
}
#[test]
fn test_slice_starts_with() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
let slice = vec.as_slice();
assert!(slice.starts_with(&[0, 1, 2]));
assert!(!slice.starts_with(&[1, 2, 3]));
}
#[test]
fn test_slice_ends_with() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
let slice = vec.as_slice();
assert!(slice.ends_with(&[7, 8, 9]));
assert!(!slice.ends_with(&[6, 7, 8]));
}
#[test]
fn test_starts_with_edge_cases() {
let empty: SegmentedVec<i32> = SegmentedVec::new();
assert!(empty.starts_with(&[])); assert!(!empty.starts_with(&[1]));
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
assert!(vec.starts_with(&[]));
let full: Vec<i32> = (0..10).collect();
assert!(vec.starts_with(&full));
let longer: Vec<i32> = (0..20).collect();
assert!(!vec.starts_with(&longer));
assert!(vec.starts_with(&[0]));
assert!(!vec.starts_with(&[1]));
}
#[test]
fn test_ends_with_edge_cases() {
let empty: SegmentedVec<i32> = SegmentedVec::new();
assert!(empty.ends_with(&[])); assert!(!empty.ends_with(&[1]));
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
assert!(vec.ends_with(&[]));
let full: Vec<i32> = (0..10).collect();
assert!(vec.ends_with(&full));
let longer: Vec<i32> = (0..20).collect();
assert!(!vec.ends_with(&longer));
assert!(vec.ends_with(&[9]));
assert!(!vec.ends_with(&[8]));
}
#[test]
fn test_starts_with_across_segments() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..1000);
assert!(vec.starts_with(&[0, 1, 2, 3, 4]));
let prefix: Vec<i32> = (0..100).collect();
assert!(vec.starts_with(&prefix));
assert!(!vec.starts_with(&[1, 2, 3]));
}
#[test]
fn test_ends_with_across_segments() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..1000);
assert!(vec.ends_with(&[997, 998, 999]));
let suffix: Vec<i32> = (900..1000).collect();
assert!(vec.ends_with(&suffix));
assert!(!vec.ends_with(&[996, 997, 998]));
}
#[test]
fn test_slice_eq() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend(0..10);
let slice = vec.as_slice();
assert_eq!(slice, (0..10).collect::<Vec<_>>());
}
#[test]
fn test_min_non_zero_cap() {
let mut vec_u8: SegmentedVec<u8> = SegmentedVec::new();
vec_u8.push(1);
assert_eq!(vec_u8.capacity(), 8);
let mut vec_i32: SegmentedVec<i32> = SegmentedVec::new();
vec_i32.push(1);
assert_eq!(vec_i32.capacity(), 4);
for i in 0u8..100 {
vec_u8.push(i);
}
for i in 0..101 {
assert_eq!(vec_u8[i], if i == 0 { 1 } else { (i - 1) as u8 });
}
}
#[test]
fn test_extend_from_copy_slice() {
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
let data: Vec<i32> = (0..100).collect();
vec.extend_from_copy_slice(&data);
assert_eq!(vec.len(), 100);
for i in 0..100 {
assert_eq!(vec[i], i as i32);
}
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.push(999);
vec.push(998);
vec.extend_from_copy_slice(&data[..10]);
assert_eq!(vec.len(), 12);
assert_eq!(vec[0], 999);
assert_eq!(vec[1], 998);
for i in 0..10 {
assert_eq!(vec[i + 2], i as i32);
}
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend_from_copy_slice(&[]);
assert!(vec.is_empty());
let mut vec: SegmentedVec<i32> = SegmentedVec::new();
vec.extend_from_copy_slice(&[1, 2, 3]); assert_eq!(vec.len(), 3);
vec.push(4); vec.push(5);
vec.push(6);
assert_eq!(vec.len(), 6);
for i in 0..6 {
assert_eq!(vec[i], (i + 1) as i32);
}
}
}