#![deny(missing_docs, missing_debug_implementations, unsafe_code)]
extern crate id_set;
#[cfg(test)]
mod tests;
pub use id_set::Id;
use std::iter::FromIterator;
use std::ops::{Index, IndexMut};
use std::{cmp, fmt, mem};
use std::{slice, vec};
use id_set::IdSet;
#[derive(Clone)]
pub struct IdMap<T> {
ids: IdSet,
values: Vec<Option<T>>,
space: Id,
}
impl<T> IdMap<T> {
#[inline]
pub fn new() -> Self {
IdMap {
ids: IdSet::new(),
values: Vec::new(),
space: 0,
}
}
#[inline]
pub fn with_capacity(cap: usize) -> Self {
IdMap {
ids: IdSet::with_capacity(cap),
values: Vec::with_capacity(cap),
space: 0,
}
}
#[inline]
pub fn clear(&mut self) {
self.drop_values();
self.ids.clear();
}
#[inline]
pub fn next_id(&self) -> Id {
self.space
}
#[inline]
pub fn len(&self) -> usize {
self.ids.len()
}
#[inline]
pub fn capacity(&self) -> usize {
self.ids.capacity()
}
#[inline]
pub fn reserve(&mut self, cap: usize) {
self.ids.reserve(cap);
self.values.reserve(cap);
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.ids.shrink_to_fit();
self.values.truncate(self.ids.capacity());
self.values.shrink_to(self.ids.capacity());
}
#[inline]
pub fn as_set(&self) -> &IdSet {
&self.ids
}
#[inline]
pub fn insert(&mut self, val: T) -> Id {
let id = self.space;
if id == self.values.len() {
self.values.resize_with(id + 1, Default::default);
}
self.values[id] = Some(val);
self.ids.insert(id);
self.find_space();
id
}
#[inline]
pub fn insert_at(&mut self, id: Id, val: T) -> Option<T> {
if self.ids.insert(id) {
if id == self.space {
self.find_space();
}
if self.values.len() < id + 1 {
self.values.resize_with(id + 1, Default::default);
}
self.values[id] = Some(val);
None
} else {
Some(mem::replace(&mut self.values[id].as_mut().unwrap(), val))
}
}
#[inline]
pub fn remove(&mut self, id: Id) -> Option<T> {
if self.ids.remove(id) {
self.space = cmp::min(self.space, id);
self.values[id].take()
} else {
None
}
}
#[inline]
pub fn get_or_insert(&mut self, id: Id, val: T) -> &mut T {
self.get_or_insert_with(id, || val)
}
#[inline]
pub fn get_or_insert_with<F: FnOnce() -> T>(&mut self, id: Id, f: F) -> &mut T {
if self.ids.insert(id) {
if id == self.space {
self.find_space();
}
if self.values.len() < id + 1 {
self.values.resize_with(id + 1, Default::default);
}
self.values[id] = Some(f());
}
self.values[id].as_mut().unwrap()
}
#[inline]
pub fn remove_set(&mut self, set: &IdSet) {
{
let mut iter = self.ids.intersection(set).into_iter();
if let Some(first) = iter.next() {
self.space = cmp::min(self.space, first);
self.values[first] = None;
for id in iter {
self.values[id] = None;
}
}
}
self.ids.inplace_difference(set);
}
#[inline]
pub fn retain<F: FnMut(Id, &T) -> bool>(&mut self, mut pred: F) {
let ids = &mut self.ids;
let values = &mut self.values;
let space = &mut self.space;
ids.retain(|id| {
if pred(id, values[id].as_ref().unwrap()) {
true
} else {
*space = cmp::min(*space, id);
values[id] = None;
false
}
})
}
#[inline]
pub fn contains(&self, id: Id) -> bool {
self.ids.contains(id)
}
#[inline]
pub fn get(&self, id: Id) -> Option<&T> {
if self.ids.contains(id) {
Some(self.values[id].as_ref().unwrap())
} else {
None
}
}
#[inline]
pub fn get_mut(&mut self, id: Id) -> Option<&mut T> {
if self.ids.contains(id) {
Some(self.values[id].as_mut().unwrap())
} else {
None
}
}
#[inline]
pub fn ids(&self) -> Ids {
Ids {
ids: self.ids.iter(),
}
}
#[inline]
pub fn values(&self) -> Values<T> {
Values {
ids: self.ids.iter(),
values: &self.values,
}
}
#[inline]
pub fn values_mut(&mut self) -> ValuesMut<T> {
ValuesMut {
ids: self.ids.iter(),
prev: None,
values: self.values.iter_mut(),
}
}
#[inline]
pub fn iter(&self) -> Iter<T> {
Iter {
ids: self.ids.iter(),
values: &self.values,
}
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut {
ids: self.ids.iter(),
prev: None,
values: self.values.iter_mut(),
}
}
#[inline]
pub fn into_iter(self) -> IntoIter<T> {
IntoIter {
ids: self.ids.into_iter(),
prev: None,
values: self.values.into_iter(),
}
}
#[cfg(test)]
fn assert_invariant(&self) {
for id in 0..self.space {
assert!(self.ids.contains(id));
}
assert!(!self.ids.contains(self.space));
for id in &self.ids {
assert!(id < self.values.len())
}
}
fn drop_values(&mut self) {
for id in &self.ids {
self.values[id] = None;
}
}
fn find_space(&mut self) {
self.space += 1;
while self.ids.contains(self.space) {
self.space += 1;
}
}
}
impl<T: fmt::Debug> fmt::Debug for IdMap<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{{")?;
let mut iter = self.iter();
if let Some((id, val)) = iter.next() {
write!(f, "{:?}: {:?}", id, val)?;
for (id, val) in iter {
write!(f, ", {:?}: {:?}", id, val)?;
}
}
write!(f, "}}")
}
}
impl<T> Default for IdMap<T> {
#[inline]
fn default() -> Self {
IdMap::new()
}
}
impl<T: Eq> Eq for IdMap<T> {}
impl<T: PartialEq> PartialEq for IdMap<T> {
fn eq(&self, other: &Self) -> bool {
self.ids == other.ids
&& self
.ids
.iter()
.zip(&other.ids)
.all(|(l, r)| self.values[l].as_ref().unwrap() == other.values[r].as_ref().unwrap())
}
}
impl<T> Extend<T> for IdMap<T> {
#[inline]
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for val in iter {
self.insert(val);
}
}
}
impl<T> FromIterator<T> for IdMap<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let values = Vec::from_iter(iter.into_iter().map(Some));
let space = values.len();
let ids = IdSet::new_filled(values.len());
IdMap { values, space, ids }
}
}
impl<T> FromIterator<(Id, T)> for IdMap<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = (Id, T)>>(iter: I) -> Self {
let iter = iter.into_iter();
let mut map = IdMap::with_capacity(iter.size_hint().0);
for (id, val) in iter {
map.insert_at(id, val);
}
map
}
}
impl<'a, T> IntoIterator for &'a IdMap<T> {
type Item = (Id, &'a T);
type IntoIter = Iter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T> IntoIterator for &'a mut IdMap<T> {
type Item = (Id, &'a mut T);
type IntoIter = IterMut<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<T> IntoIterator for IdMap<T> {
type Item = (Id, T);
type IntoIter = IntoIter<T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.into_iter()
}
}
impl<T> Index<Id> for IdMap<T> {
type Output = T;
#[inline]
fn index(&self, id: Id) -> &Self::Output {
assert!(self.ids.contains(id), "id {} out of bounds", id);
self.values[id].as_ref().unwrap()
}
}
impl<T> IndexMut<Id> for IdMap<T> {
#[inline]
fn index_mut(&mut self, id: Id) -> &mut Self::Output {
assert!(self.ids.contains(id), "id {} out of bounds", id);
self.values[id].as_mut().unwrap()
}
}
#[derive(Clone, Debug)]
pub struct Ids<'a> {
ids: id_set::Iter<'a>,
}
impl<'a> Iterator for Ids<'a> {
type Item = Id;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.ids.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.ids.size_hint()
}
}
impl<'a> ExactSizeIterator for Ids<'a> {
#[inline]
fn len(&self) -> usize {
self.ids.len()
}
}
#[derive(Debug)]
pub struct Values<'a, T: 'a> {
ids: id_set::Iter<'a>,
values: &'a [Option<T>],
}
impl<'a, T: 'a> Iterator for Values<'a, T> {
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.ids.next().map(|id| self.values[id].as_ref().unwrap())
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.ids.size_hint()
}
}
impl<'a, T: 'a> ExactSizeIterator for Values<'a, T> {
#[inline]
fn len(&self) -> usize {
self.ids.len()
}
}
impl<'a, T: 'a> Clone for Values<'a, T> {
#[inline]
fn clone(&self) -> Self {
Values {
ids: self.ids.clone(),
values: self.values,
}
}
}
#[derive(Debug)]
pub struct ValuesMut<'a, T: 'a> {
ids: id_set::Iter<'a>,
prev: Option<Id>,
values: slice::IterMut<'a, Option<T>>,
}
impl<'a, T: 'a> Iterator for ValuesMut<'a, T> {
type Item = &'a mut T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let id = self.ids.next()?;
let n = match self.prev {
Some(prev) => id - prev - 1,
None => 0,
};
self.prev = Some(id);
Some(self.values.nth(n).unwrap().as_mut().unwrap())
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.ids.size_hint()
}
}
impl<'a, T: 'a> ExactSizeIterator for ValuesMut<'a, T> {
#[inline]
fn len(&self) -> usize {
self.ids.len()
}
}
#[derive(Debug)]
pub struct Iter<'a, T: 'a> {
ids: id_set::Iter<'a>,
values: &'a [Option<T>],
}
impl<'a, T: 'a> Iterator for Iter<'a, T> {
type Item = (Id, &'a T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.ids
.next()
.map(|id| (id, self.values[id].as_ref().unwrap()))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.ids.size_hint()
}
}
impl<'a, T: 'a> ExactSizeIterator for Iter<'a, T> {
#[inline]
fn len(&self) -> usize {
self.ids.len()
}
}
impl<'a, T: 'a> Clone for Iter<'a, T> {
#[inline]
fn clone(&self) -> Self {
Iter {
ids: self.ids.clone(),
values: self.values,
}
}
}
#[derive(Debug)]
pub struct IterMut<'a, T: 'a> {
ids: id_set::Iter<'a>,
prev: Option<Id>,
values: slice::IterMut<'a, Option<T>>,
}
impl<'a, T: 'a> Iterator for IterMut<'a, T> {
type Item = (Id, &'a mut T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let id = self.ids.next()?;
let n = match self.prev {
Some(prev) => id - prev - 1,
None => 0,
};
self.prev = Some(id);
Some((
id,
self.values.nth(n).unwrap().as_mut().expect("id not in map"),
))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.ids.size_hint()
}
}
impl<'a, T: 'a> ExactSizeIterator for IterMut<'a, T> {
#[inline]
fn len(&self) -> usize {
self.ids.len()
}
}
#[derive(Clone, Debug)]
pub struct IntoIter<T> {
ids: id_set::IntoIter,
prev: Option<Id>,
values: vec::IntoIter<Option<T>>,
}
impl<T> Iterator for IntoIter<T> {
type Item = (Id, T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let id = self.ids.next()?;
let n = match self.prev {
Some(prev) => id - prev - 1,
None => 0,
};
self.prev = Some(id);
Some((id, self.values.nth(n).unwrap().expect("id not in map")))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.ids.size_hint()
}
}