use std::collections::{ binary_heap, BinaryHeap };
use std::cmp::Reverse;
use std::convert;
use std::fmt;
use std::hash::{ Hash, Hasher };
use std::iter::{ Enumerate, FilterMap };
use std::ops::Index;
use std::slice::SliceIndex;
#[cfg(feature = "serde")]
use serde::{ Deserialize, Deserializer, Serialize, Serializer };
pub type TransformTable = std::collections::BTreeMap<usize, usize>;
#[derive(Clone, Default)]
pub struct PackingList<T> {
list: Vec<Option<T>>,
empty_spots: BinaryHeap<Reverse<usize>>
}
impl<T> PackingList<T> {
#[inline]
pub fn new() -> Self {
PackingList {
list: Vec::new(),
empty_spots: BinaryHeap::new()
}
}
#[inline]
pub fn clear(&mut self) {
self.list.clear();
self.empty_spots.clear();
}
#[inline]
pub fn is_empty(&self) -> bool {
self.count() == 0
}
#[inline]
pub fn list(&self) -> &'_ Vec<Option<T>> {
&self.list
}
#[inline]
pub fn count(&self) -> usize {
self.list.len() - self.empty_spots.len()
}
pub fn pack(&mut self) -> TransformTable {
let mut old_list: Vec<Option<T>> = Vec::with_capacity(self.count());
std::mem::swap(&mut old_list, &mut self.list);
self.empty_spots.clear();
let mut table = TransformTable::new();
for (i, v) in old_list.into_iter().enumerate().filter(|(_, v)| v.is_some()) {
self.list.push(v);
table.insert(i, self.list.len() - 1);
}
table
}
pub fn combine(&mut self, other: &mut PackingList<T>) -> TransformTable {
let mut old_other_list: Vec<Option<T>> = Vec::new();
std::mem::swap(&mut old_other_list, &mut other.list);
other.empty_spots.clear();
let mut table = TransformTable::new();
let iter = old_other_list
.into_iter()
.enumerate()
.filter(|(_, v)| v.is_some())
.map(|(i, v)| (i, v.unwrap()));
for (i, v) in iter {
table.insert(i, self.add(v));
}
table
}
#[inline]
pub fn index_iter(&self) -> IndexIter<'_> {
IndexIter {
current: 0,
end: self.list.len(),
heap_iter: self.empty_spots.iter().peekable()
}
}
#[inline]
pub fn item_iter(&self) -> ItemIter<'_, T> {
ItemIter {
list: &self.list,
index_iter: self.index_iter()
}
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
IterMut {
items: self.item_iter()
}
}
#[inline]
pub fn add(&mut self, data: T) -> usize {
if let Some(idx) = self.empty_spots.pop() {
self.list[idx.0] = Some(data);
idx.0
} else {
self.list.push(Some(data));
self.list.len() - 1
}
}
#[inline]
pub fn remove(&mut self, idx: usize) -> Option<T> {
self.list.get_mut(idx)?.take().and_then(|v| {
if idx == self.list.len() - 1 {
self.list.pop();
} else {
self.empty_spots.push(Reverse(idx));
}
Some(v)
})
}
#[inline]
pub fn get_mut(&mut self, idx: usize) -> Option<&mut T> {
self.list.get_mut(idx)?.as_mut()
}
#[allow(dead_code)]
fn trim_vec(list: &mut Vec<Option<T>>) {
while list.last().is_some_and(|opt| opt.is_none()) {
list.pop();
}
}
}
impl<T, I: SliceIndex<[Option<T>]>> Index<I> for PackingList<T> {
type Output = I::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output {
self.list.index(index)
}
}
impl<T> fmt::Debug for PackingList<T> where T: fmt::Debug {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[")?;
let len = self.list.len();
for opt in &self.list[0..(len - 1)] {
match opt {
Some(v) => write!(f, "{:?}, ", v)?,
None => write!(f, "_, ")?
};
}
match self.list.last() {
Some(Some(v)) => write!(f, "{:?}]", v)?,
_ => write!(f, "]")?
};
Ok(())
}
}
impl<T> FromIterator<Option<T>> for PackingList<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = Option<T>>>(iter: I) -> Self {
Self::from(iter.into_iter().collect::<Vec<Option<T>>>())
}
}
#[cfg(feature = "serde")]
impl<T: Serialize> Serialize for PackingList<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.list.serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, T: Deserialize<'de>> Deserialize<'de> for PackingList<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>
{
Ok(Self::from(Vec::deserialize(deserializer)?))
}
}
pub type ListIter<T> = FilterMap<Enumerate<std::vec::IntoIter<Option<T>>>, fn((usize, Option<T>)) -> Option<(usize, T)>>;
impl<T> IntoIterator for PackingList<T> {
type Item = (usize, T);
type IntoIter = ListIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.list.into_iter()
.enumerate()
.filter_map(|(i, opt)| opt.and_then(|v| Some((i, v))))
}
}
impl<T> convert::From<Vec<Option<T>>> for PackingList<T> {
fn from(vec: Vec<Option<T>>) -> Self {
let empty_spots: BinaryHeap<Reverse<usize>> = vec.iter()
.enumerate()
.filter(|(_, opt)| opt.is_none())
.map(|(i, _)| Reverse(i)).collect();
PackingList {
list: vec,
empty_spots
}
}
}
impl<T> Hash for PackingList<T> where T: Hash {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.list.hash(state);
}
}
impl<T: PartialEq> PartialEq for PackingList<Option<T>> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.list == other.list
}
}
use std::iter::Peekable;
pub struct IndexIter<'a> {
current: usize,
end: usize,
heap_iter: Peekable<binary_heap::Iter<'a, Reverse<usize>>>
}
impl<'a> Iterator for IndexIter<'a> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if let Some(peek) = self.heap_iter.peek() {
if self.current < peek.0 {
self.current += 1;
Some(self.current - 1)
} else {
let mut popped = self.heap_iter.next().unwrap().0;
while self.heap_iter.peek().is_some_and(|v| popped == v.0 - 1) {
popped = self.heap_iter.next().unwrap().0;
}
if popped + 1 < self.end {
self.current = popped + 2;
Some(self.current - 1)
} else {
None
}
}
} else if self.current < self.end {
self.current += 1;
Some(self.current - 1)
} else {
None
}
}
}
pub struct ItemIter<'a, T> {
list: &'a Vec<Option<T>>,
index_iter: IndexIter<'a>
}
impl<'a, T> Iterator for ItemIter<'a, T> {
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self.index_iter.next() {
Some(i) => self.list[i].as_ref(),
None => None
}
}
}
pub struct IterMut<'a, T> {
items: ItemIter<'a, T>
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self.items.next() {
Some(r) => {
unsafe {
(r as *const T).cast_mut().as_mut()
}
},
None => None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn add_does_fill() {
let mut list = PackingList::from(vec![Some(0), None, Some(2), None, Some(4)]);
assert_eq!(list.add(1), 1);
assert_eq!(list.add(3), 3);
assert_eq!(*list.list(), [Some(0), Some(1), Some(2), Some(3), Some(4)]);
}
#[test]
fn add_does_push() {
let mut list = PackingList::from(vec![Some(0), Some(1)]);
assert_eq!(list.add(2), 2);
assert_eq!(*list.list(), [Some(0), Some(1), Some(2)]);
}
#[test]
fn remove_makes_empty() {
let mut list = PackingList::from(vec![None, Some(1)]);
assert_eq!(list.remove(1), Some(1));
assert!(list.is_empty());
}
#[test]
fn remove_none_is_none() {
let vec = vec![Some(0), None, Some(1)];
let mut list = PackingList::from(vec.clone());
assert_eq!(list.remove(1), None);
assert_eq!(*list.list(), vec);
}
#[test]
fn into_iter() {
let mut iter = PackingList::from(vec![None, Some(1), Some(2), None, None, None, Some(3), None, Some(4)])
.into_iter();
assert_eq!(iter.next(), Some((1, 1)));
assert_eq!(iter.next(), Some((2, 2)));
assert_eq!(iter.next(), Some((6, 3)));
assert_eq!(iter.next(), Some((8, 4)));
assert_eq!(iter.next(), None);
}
}