use std::collections::VecDeque;
#[derive(Default, Clone, Debug)]
pub struct StableIndexDeque<T> {
vec: VecDeque<T>,
index_offset: usize,
}
impl<T> re_byte_size::SizeBytes for StableIndexDeque<T>
where
T: re_byte_size::SizeBytes,
{
fn heap_size_bytes(&self) -> u64 {
let Self {
vec,
index_offset: _,
} = self;
vec.heap_size_bytes()
}
}
impl<T> StableIndexDeque<T> {
#[inline]
pub fn new() -> Self {
Self {
vec: VecDeque::new(),
index_offset: 0,
}
}
pub fn from_iter_with_offset(index_offset: usize, iter: impl IntoIterator<Item = T>) -> Self {
Self {
vec: VecDeque::from_iter(iter),
index_offset,
}
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self {
vec: VecDeque::with_capacity(capacity),
index_offset: 0,
}
}
#[inline]
pub fn push_back(&mut self, value: T) {
self.vec.push_back(value);
}
#[inline]
pub fn pop_front(&mut self) -> Option<T> {
self.vec.pop_front().inspect(|_| self.index_offset += 1)
}
pub fn pop_back(&mut self) -> Option<T> {
self.vec.pop_back()
}
#[inline]
pub fn extend(&mut self, values: impl IntoIterator<Item = T>) {
self.vec.extend(values);
}
#[inline]
pub fn iter(&self) -> impl DoubleEndedIterator<Item = &T> {
self.vec.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
self.vec.iter_mut()
}
pub fn iter_indexed(&self) -> impl DoubleEndedIterator<Item = (usize, &T)> + ExactSizeIterator {
let offset = self.index_offset;
self.vec
.iter()
.enumerate()
.map(move |(i, v)| (i + offset, v))
}
pub fn iter_indexed_mut(
&mut self,
) -> impl DoubleEndedIterator<Item = (usize, &mut T)> + ExactSizeIterator {
self.vec
.iter_mut()
.enumerate()
.map(|(i, v)| (i + self.index_offset, v))
}
#[inline]
pub fn back(&self) -> Option<&T> {
self.vec.back()
}
#[inline]
pub fn back_mut(&mut self) -> Option<&mut T> {
self.vec.back_mut()
}
#[inline]
pub fn front(&self) -> Option<&T> {
self.vec.front()
}
#[inline]
pub fn front_mut(&mut self) -> Option<&mut T> {
self.vec.front_mut()
}
pub fn remove_all_with_index_larger_equal(&mut self, first_index_not_contained: usize) {
let new_len = first_index_not_contained.saturating_sub(self.index_offset);
self.vec.truncate(new_len);
}
pub fn remove_all_with_index_smaller_equal(&mut self, first_index_contained: usize) {
while !self.vec.is_empty() && first_index_contained >= self.index_offset {
self.pop_front();
}
}
pub fn position(&self, predicate: impl Fn(&T) -> bool) -> Option<usize> {
self.vec
.iter()
.position(predicate)
.map(|i| i + self.index_offset)
}
#[inline]
pub fn partition_point<F>(&self, f: F) -> usize
where
F: FnMut(&T) -> bool,
{
self.vec.partition_point(f) + self.index_offset
}
#[inline]
pub fn is_empty(&self) -> bool {
self.vec.is_empty()
}
#[inline]
pub fn get(&self, index: usize) -> Option<&T> {
self.vec.get(index.checked_sub(self.index_offset)?)
}
#[inline]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
self.vec.get_mut(index.checked_sub(self.index_offset)?)
}
#[inline]
pub fn next_index(&self) -> usize {
self.vec.len() + self.index_offset
}
#[inline]
pub fn min_index(&self) -> usize {
self.index_offset
}
#[inline]
pub fn num_elements(&self) -> usize {
self.vec.len()
}
pub fn replace(&mut self, range: std::ops::Range<usize>, replacement: Vec<T>) {
let local_start = range.start - self.index_offset;
let local_end = range.end - self.index_offset;
self.vec.drain(local_start..local_end);
let tail: Vec<T> = self.vec.drain(local_start..).collect();
self.vec.extend(replacement);
self.vec.extend(tail);
}
#[inline]
pub fn iter_index_range_clamped<'a>(
&'a self,
range: &std::ops::Range<usize>,
) -> impl DoubleEndedIterator<Item = (usize, &'a T)> + ExactSizeIterator + use<'a, T> {
let range_start = range.start.saturating_sub(self.index_offset);
let num_elements = range.end - range.start;
self.iter_indexed().skip(range_start).take(num_elements)
}
#[inline]
pub fn iter_index_range_clamped_mut<'a>(
&'a mut self,
range: &std::ops::Range<usize>,
) -> impl DoubleEndedIterator<Item = (usize, &'a mut T)> + ExactSizeIterator + use<'a, T> {
let range_start = range.start.saturating_sub(self.index_offset);
let num_elements = range.end - range.start;
self.iter_indexed_mut().skip(range_start).take(num_elements)
}
}
impl<T> std::ops::Index<usize> for StableIndexDeque<T> {
type Output = T;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
&self.vec[index - self.index_offset]
}
}
impl<T> std::ops::IndexMut<usize> for StableIndexDeque<T> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.vec[index - self.index_offset]
}
}
impl<T> FromIterator<T> for StableIndexDeque<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self {
vec: VecDeque::from_iter(iter),
index_offset: 0,
}
}
}
#[cfg(test)]
mod tests {
use super::StableIndexDeque;
#[test]
fn test_stable_index_deque() {
let mut vec = StableIndexDeque::new();
vec.push_back(1);
vec.push_back(2);
assert_eq!(vec[0], 1);
assert_eq!(vec[1], 2);
assert_eq!(vec.next_index(), 2);
assert_eq!(vec.num_elements(), 2);
assert_eq!(vec.min_index(), 0);
vec.pop_front();
assert_eq!(vec.get(0), None);
assert_eq!(vec.get(1), Some(&2));
assert_eq!(vec[1], 2);
assert_eq!(vec.get(2), None);
assert_eq!(vec.next_index(), 2);
assert_eq!(vec.vec.len(), 1);
assert_eq!(vec.num_elements(), 1);
assert_eq!(vec.min_index(), 1);
vec.pop_front();
assert_eq!(vec.vec.len(), 0);
assert_eq!(vec.next_index(), 2);
assert_eq!(vec.num_elements(), 0);
assert_eq!(vec.min_index(), 2);
}
#[test]
fn test_replace_grow() {
let mut v = (0..5).collect::<StableIndexDeque<i32>>();
v.replace(1..3, vec![10, 20, 30]);
assert_eq!(v.num_elements(), 6);
assert_eq!(v.get(0), Some(&0));
assert_eq!(v.get(1), Some(&10));
assert_eq!(v.get(2), Some(&20));
assert_eq!(v.get(3), Some(&30));
assert_eq!(v.get(4), Some(&3));
assert_eq!(v.get(5), Some(&4));
}
#[test]
fn test_replace_shrink() {
let mut v = (0..5).collect::<StableIndexDeque<i32>>();
v.replace(1..4, vec![99]);
assert_eq!(v.num_elements(), 3);
assert_eq!(v.get(0), Some(&0));
assert_eq!(v.get(1), Some(&99));
assert_eq!(v.get(2), Some(&4));
}
#[test]
fn test_replace_with_offset() {
let mut v = (0..6).collect::<StableIndexDeque<i32>>();
v.pop_front();
v.replace(2..4, vec![20, 30, 40]);
assert_eq!(v.num_elements(), 6);
assert_eq!(v.min_index(), 1);
assert_eq!(v.next_index(), 7);
assert_eq!(v.get(0), None);
assert_eq!(v.get(1), Some(&1));
assert_eq!(v.get(2), Some(&20));
assert_eq!(v.get(5), Some(&4));
assert_eq!(v.get(6), Some(&5));
}
#[test]
fn test_replace_same_size() {
let mut v = (0..5).collect::<StableIndexDeque<i32>>();
v.replace(1..3, vec![10, 20]);
assert_eq!(v.num_elements(), 5);
assert_eq!(v.get(1), Some(&10));
assert_eq!(v.get(2), Some(&20));
assert_eq!(v.get(3), Some(&3));
}
#[test]
fn test_replace_empty_replacement() {
let mut v = (0..5).collect::<StableIndexDeque<i32>>();
v.replace(1..3, vec![]);
assert_eq!(v.num_elements(), 3);
assert_eq!(v.get(0), Some(&0));
assert_eq!(v.get(1), Some(&3));
assert_eq!(v.get(2), Some(&4));
}
}