pub use mutable_keys::MutableKeys;
#[cfg(feature = "rayon")]
pub use ::rayon::map as rayon;
use std::hash::Hash;
use std::hash::BuildHasher;
use std::hash::Hasher;
use std::iter::FromIterator;
use std::collections::hash_map::RandomState;
use std::ops::RangeFull;
use std::cmp::{max, Ordering};
use std::fmt;
use std::mem::{replace};
use std::marker::PhantomData;
use util::{third, ptrdistance, enumerate};
use equivalent::Equivalent;
use {
Bucket,
Entries,
HashValue,
};
fn hash_elem_using<B: BuildHasher, K: ?Sized + Hash>(build: &B, k: &K) -> HashValue {
let mut h = build.build_hasher();
k.hash(&mut h);
HashValue(h.finish() as usize)
}
#[derive(Debug)]
struct ShortHash<Sz>(usize, PhantomData<Sz>);
impl<Sz> ShortHash<Sz> {
fn into_hash(self) -> HashValue {
HashValue(self.0)
}
}
impl<Sz> Copy for ShortHash<Sz> { }
impl<Sz> Clone for ShortHash<Sz> {
#[inline]
fn clone(&self) -> Self { *self }
}
impl<Sz> PartialEq for ShortHash<Sz> {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.0 == rhs.0
}
}
impl<Sz> PartialEq<HashValue> for ShortHash<Sz> where Sz: Size {
#[inline]
fn eq(&self, rhs: &HashValue) -> bool {
if Sz::is_64_bit() {
self.0 == rhs.0
} else {
lo32(self.0 as u64) == lo32(rhs.0 as u64)
}
}
}
impl<Sz> From<ShortHash<Sz>> for HashValue {
fn from(x: ShortHash<Sz>) -> Self { HashValue(x.0) }
}
#[derive(Copy)]
struct Pos {
index: u64,
}
impl Clone for Pos {
#[inline(always)]
fn clone(&self) -> Self { *self }
}
impl fmt::Debug for Pos {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.pos() {
Some(i) => write!(f, "Pos({} / {:x})", i, self.index),
None => write!(f, "Pos(None)"),
}
}
}
impl Pos {
#[inline]
fn none() -> Self { Pos { index: !0 } }
#[inline]
fn is_none(&self) -> bool { self.index == !0 }
#[inline]
fn pos(&self) -> Option<usize> {
if self.index == !0 { None } else { Some(lo32(self.index as u64)) }
}
#[inline]
fn set_pos<Sz>(&mut self, i: usize)
where Sz: Size,
{
debug_assert!(!self.is_none());
if Sz::is_64_bit() {
self.index = i as u64;
} else {
self.index = i as u64 | ((self.index >> 32) << 32)
}
}
#[inline]
fn with_hash<Sz>(i: usize, hash: HashValue) -> Self
where Sz: Size
{
if Sz::is_64_bit() {
Pos {
index: i as u64,
}
} else {
Pos {
index: i as u64 | ((hash.0 as u64) << 32)
}
}
}
#[inline]
fn resolve<Sz>(&self) -> Option<(usize, ShortHashProxy<Sz>)>
where Sz: Size
{
if Sz::is_64_bit() {
if !self.is_none() {
Some((self.index as usize, ShortHashProxy::new(0)))
} else {
None
}
} else {
if !self.is_none() {
let (i, hash) = split_lo_hi(self.index);
Some((i as usize, ShortHashProxy::new(hash as usize)))
} else {
None
}
}
}
#[inline]
fn resolve_existing_index<Sz>(&self) -> usize
where Sz: Size
{
debug_assert!(!self.is_none(), "datastructure inconsistent: none where valid Pos expected");
if Sz::is_64_bit() {
self.index as usize
} else {
let (i, _) = split_lo_hi(self.index);
i as usize
}
}
}
#[inline]
fn lo32(x: u64) -> usize { (x & 0xFFFF_FFFF) as usize }
#[inline]
fn split_lo_hi(x: u64) -> (u32, u32) { (x as u32, (x >> 32) as u32) }
struct ShortHashProxy<Sz>(usize, PhantomData<Sz>);
impl<Sz> ShortHashProxy<Sz>
where Sz: Size
{
fn new(x: usize) -> Self {
ShortHashProxy(x, PhantomData)
}
fn get_short_hash<K, V>(&self, entries: &[Bucket<K, V>], index: usize) -> ShortHash<Sz> {
if Sz::is_64_bit() {
ShortHash(entries[index].hash.0, PhantomData)
} else {
ShortHash(self.0, PhantomData)
}
}
}
#[derive(Clone)]
pub struct IndexMap<K, V, S = RandomState> {
core: OrderMapCore<K, V>,
hash_builder: S,
}
#[derive(Clone)]
struct OrderMapCore<K, V> {
pub(crate) mask: usize,
pub(crate) indices: Box<[Pos]>,
pub(crate) entries: Vec<Bucket<K, V>>,
}
#[inline(always)]
fn desired_pos(mask: usize, hash: HashValue) -> usize {
hash.0 & mask
}
impl<K, V, S> Entries for IndexMap<K, V, S> {
type Entry = Bucket<K, V>;
fn into_entries(self) -> Vec<Self::Entry> {
self.core.entries
}
fn as_entries(&self) -> &[Self::Entry] {
&self.core.entries
}
fn as_entries_mut(&mut self) -> &mut [Self::Entry] {
&mut self.core.entries
}
fn with_entries<F>(&mut self, f: F)
where F: FnOnce(&mut [Self::Entry])
{
let side_index = self.core.save_hash_index();
f(&mut self.core.entries);
self.core.restore_hash_index(side_index);
}
}
#[inline(always)]
fn probe_distance(mask: usize, hash: HashValue, current: usize) -> usize {
current.wrapping_sub(desired_pos(mask, hash)) & mask
}
enum Inserted<V> {
Done,
Swapped { prev_value: V },
RobinHood {
probe: usize,
old_pos: Pos,
}
}
impl<K, V, S> fmt::Debug for IndexMap<K, V, S>
where K: fmt::Debug + Hash + Eq,
V: fmt::Debug,
S: BuildHasher,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()?;
if cfg!(not(feature = "test_debug")) {
return Ok(());
}
writeln!(f)?;
for (i, index) in enumerate(&*self.core.indices) {
write!(f, "{}: {:?}", i, index)?;
if let Some(pos) = index.pos() {
let hash = self.core.entries[pos].hash;
let key = &self.core.entries[pos].key;
let desire = desired_pos(self.core.mask, hash);
write!(f, ", desired={}, probe_distance={}, key={:?}",
desire,
probe_distance(self.core.mask, hash, i),
key)?;
}
writeln!(f)?;
}
writeln!(f, "cap={}, raw_cap={}, entries.cap={}",
self.capacity(),
self.raw_capacity(),
self.core.entries.capacity())?;
Ok(())
}
}
#[inline]
fn usable_capacity(cap: usize) -> usize {
cap - cap / 4
}
#[inline]
fn to_raw_capacity(n: usize) -> usize {
n + n / 3
}
macro_rules! probe_loop {
($probe_var: ident < $len: expr, $body: expr) => {
loop {
if $probe_var < $len {
$body
$probe_var += 1;
} else {
$probe_var = 0;
}
}
}
}
impl<K, V> IndexMap<K, V> {
pub fn new() -> Self {
Self::with_capacity(0)
}
pub fn with_capacity(n: usize) -> Self {
Self::with_capacity_and_hasher(n, <_>::default())
}
}
impl<K, V, S> IndexMap<K, V, S>
{
pub fn with_capacity_and_hasher(n: usize, hash_builder: S) -> Self
where S: BuildHasher
{
if n == 0 {
IndexMap {
core: OrderMapCore {
mask: 0,
indices: Box::new([]),
entries: Vec::new(),
},
hash_builder,
}
} else {
let raw = to_raw_capacity(n);
let raw_cap = max(raw.next_power_of_two(), 8);
IndexMap {
core: OrderMapCore {
mask: raw_cap.wrapping_sub(1),
indices: vec![Pos::none(); raw_cap].into_boxed_slice(),
entries: Vec::with_capacity(usable_capacity(raw_cap)),
},
hash_builder,
}
}
}
pub fn len(&self) -> usize { self.core.len() }
pub fn is_empty(&self) -> bool { self.len() == 0 }
pub fn with_hasher(hash_builder: S) -> Self
where S: BuildHasher
{
Self::with_capacity_and_hasher(0, hash_builder)
}
pub fn hasher(&self) -> &S
where S: BuildHasher
{
&self.hash_builder
}
pub fn capacity(&self) -> usize {
self.core.capacity()
}
#[inline]
fn size_class_is_64bit(&self) -> bool {
self.core.size_class_is_64bit()
}
#[inline(always)]
fn raw_capacity(&self) -> usize {
self.core.raw_capacity()
}
}
impl<K, V> OrderMapCore<K, V> {
#[cfg(not(feature = "test_low_transition_point"))]
fn size_class_is_64bit(&self) -> bool {
usize::max_value() > u32::max_value() as usize &&
self.raw_capacity() >= u32::max_value() as usize
}
#[cfg(feature = "test_low_transition_point")]
fn size_class_is_64bit(&self) -> bool {
self.raw_capacity() >= 64
}
#[inline(always)]
fn raw_capacity(&self) -> usize {
self.indices.len()
}
}
trait Size {
fn is_64_bit() -> bool;
fn is_same_size<T: Size>() -> bool {
Self::is_64_bit() == T::is_64_bit()
}
}
impl Size for u32 {
#[inline]
fn is_64_bit() -> bool { false }
}
impl Size for u64 {
#[inline]
fn is_64_bit() -> bool { true }
}
macro_rules! dispatch_32_vs_64 {
($self_:ident . $method:ident::<$($t:ty),*>($($arg:expr),*)) => {
if $self_.size_class_is_64bit() {
$self_.$method::<u64, $($t),*>($($arg),*)
} else {
$self_.$method::<u32, $($t),*>($($arg),*)
}
};
($self_:ident . $method:ident ($($arg:expr),*)) => {
if $self_.size_class_is_64bit() {
$self_.$method::<u64>($($arg),*)
} else {
$self_.$method::<u32>($($arg),*)
}
};
($self_:ident => $function:ident ($($arg:expr),*)) => {
if $self_.size_class_is_64bit() {
$function::<u64>($($arg),*)
} else {
$function::<u32>($($arg),*)
}
};
}
pub enum Entry<'a, K: 'a, V: 'a> {
Occupied(OccupiedEntry<'a, K, V>),
Vacant(VacantEntry<'a, K, V>),
}
impl<'a, K, V> Entry<'a, K, V> {
pub fn or_insert(self, default: V) -> &'a mut V {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default),
}
}
pub fn or_insert_with<F>(self, call: F) -> &'a mut V
where F: FnOnce() -> V,
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(call()),
}
}
pub fn key(&self) -> &K {
match *self {
Entry::Occupied(ref entry) => entry.key(),
Entry::Vacant(ref entry) => entry.key(),
}
}
pub fn index(&self) -> usize {
match *self {
Entry::Occupied(ref entry) => entry.index(),
Entry::Vacant(ref entry) => entry.index(),
}
}
pub fn and_modify<F>(self, f: F) -> Self
where F: FnOnce(&mut V),
{
match self {
Entry::Occupied(mut o) => {
f(o.get_mut());
Entry::Occupied(o)
}
x => x,
}
}
pub fn or_default(self) -> &'a mut V
where V: Default
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(V::default()),
}
}
}
impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Entry<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Entry::Vacant(ref v) => {
f.debug_tuple("Entry")
.field(v)
.finish()
}
Entry::Occupied(ref o) => {
f.debug_tuple("Entry")
.field(o)
.finish()
}
}
}
}
pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
map: &'a mut OrderMapCore<K, V>,
key: K,
probe: usize,
index: usize,
}
impl<'a, K, V> OccupiedEntry<'a, K, V> {
pub fn key(&self) -> &K { &self.key }
pub fn get(&self) -> &V {
&self.map.entries[self.index].value
}
pub fn get_mut(&mut self) -> &mut V {
&mut self.map.entries[self.index].value
}
pub(crate) fn replace_key(self) -> K {
let old_key = &mut self.map.entries[self.index].key;
replace(old_key, self.key)
}
pub fn index(&self) -> usize {
self.index
}
pub fn into_mut(self) -> &'a mut V {
&mut self.map.entries[self.index].value
}
pub fn insert(&mut self, value: V) -> V {
replace(self.get_mut(), value)
}
#[deprecated(note = "use `swap_remove` or `shift_remove`")]
pub fn remove(self) -> V {
self.swap_remove()
}
pub fn swap_remove(self) -> V {
self.swap_remove_entry().1
}
pub fn shift_remove(self) -> V {
self.shift_remove_entry().1
}
#[deprecated(note = "use `swap_remove_entry` or `shift_remove_entry`")]
pub fn remove_entry(self) -> (K, V) {
self.swap_remove_entry()
}
pub fn swap_remove_entry(self) -> (K, V) {
self.map.swap_remove_found(self.probe, self.index)
}
pub fn shift_remove_entry(self) -> (K, V) {
self.map.shift_remove_found(self.probe, self.index)
}
}
impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for OccupiedEntry<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("OccupiedEntry")
.field("key", self.key())
.field("value", self.get())
.finish()
}
}
pub struct VacantEntry<'a, K: 'a, V: 'a> {
map: &'a mut OrderMapCore<K, V>,
key: K,
hash: HashValue,
probe: usize,
}
impl<'a, K, V> VacantEntry<'a, K, V> {
pub fn key(&self) -> &K { &self.key }
pub fn into_key(self) -> K { self.key }
pub fn index(&self) -> usize { self.map.len() }
pub fn insert(self, value: V) -> &'a mut V {
if self.map.size_class_is_64bit() {
self.insert_impl::<u64>(value)
} else {
self.insert_impl::<u32>(value)
}
}
fn insert_impl<Sz>(self, value: V) -> &'a mut V
where Sz: Size
{
let index = self.map.entries.len();
self.map.entries.push(Bucket { hash: self.hash, key: self.key, value });
let old_pos = Pos::with_hash::<Sz>(index, self.hash);
self.map.insert_phase_2::<Sz>(self.probe, old_pos);
&mut {self.map}.entries[index].value
}
}
impl<'a, K: 'a + fmt::Debug, V: 'a> fmt::Debug for VacantEntry<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("VacantEntry")
.field(self.key())
.finish()
}
}
impl<K, V, S> IndexMap<K, V, S>
where K: Hash + Eq,
S: BuildHasher,
{
fn entry_phase_1<Sz>(&mut self, key: K) -> Entry<K, V>
where Sz: Size
{
let hash = hash_elem_using(&self.hash_builder, &key);
self.core.entry_phase_1::<Sz>(hash, key)
}
pub fn clear(&mut self) {
self.core.clear();
}
pub fn reserve(&mut self, additional: usize) {
if additional > 0 {
self.reserve_one();
}
}
fn insert_phase_1<Sz>(&mut self, key: K, value: V) -> Inserted<V>
where Sz: Size
{
let hash = hash_elem_using(&self.hash_builder, &key);
self.core.insert_phase_1::<Sz>(hash, key, value)
}
fn reserve_one(&mut self) {
if self.len() == self.capacity() {
dispatch_32_vs_64!(self.double_capacity());
}
}
fn double_capacity<Sz>(&mut self)
where Sz: Size,
{
self.core.double_capacity::<Sz>();
}
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
self.reserve_one();
if self.size_class_is_64bit() {
match self.insert_phase_1::<u64>(key, value) {
Inserted::Swapped { prev_value } => Some(prev_value),
Inserted::Done => None,
Inserted::RobinHood { probe, old_pos } => {
self.core.insert_phase_2::<u64>(probe, old_pos);
None
}
}
} else {
match self.insert_phase_1::<u32>(key, value) {
Inserted::Swapped { prev_value } => Some(prev_value),
Inserted::Done => None,
Inserted::RobinHood { probe, old_pos } => {
self.core.insert_phase_2::<u32>(probe, old_pos);
None
}
}
}
}
pub fn insert_full(&mut self, key: K, value: V) -> (usize, Option<V>) {
let entry = self.entry(key);
let index = entry.index();
match entry {
Entry::Occupied(mut entry) => (index, Some(entry.insert(value))),
Entry::Vacant(entry) => {
entry.insert(value);
(index, None)
}
}
}
pub fn entry(&mut self, key: K) -> Entry<K, V> {
self.reserve_one();
dispatch_32_vs_64!(self.entry_phase_1(key))
}
pub fn iter(&self) -> Iter<K, V> {
Iter {
iter: self.core.entries.iter()
}
}
pub fn iter_mut(&mut self) -> IterMut<K, V> {
IterMut {
iter: self.core.entries.iter_mut()
}
}
pub fn keys(&self) -> Keys<K, V> {
Keys {
iter: self.core.entries.iter()
}
}
pub fn values(&self) -> Values<K, V> {
Values {
iter: self.core.entries.iter()
}
}
pub fn values_mut(&mut self) -> ValuesMut<K, V> {
ValuesMut {
iter: self.core.entries.iter_mut()
}
}
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where Q: Hash + Equivalent<K>,
{
self.find(key).is_some()
}
pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
where Q: Hash + Equivalent<K>,
{
self.get_full(key).map(third)
}
pub fn get_full<Q: ?Sized>(&self, key: &Q) -> Option<(usize, &K, &V)>
where Q: Hash + Equivalent<K>,
{
if let Some((_, found)) = self.find(key) {
let entry = &self.core.entries[found];
Some((found, &entry.key, &entry.value))
} else {
None
}
}
pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V>
where Q: Hash + Equivalent<K>,
{
self.get_full_mut(key).map(third)
}
pub fn get_full_mut<Q: ?Sized>(&mut self, key: &Q)
-> Option<(usize, &K, &mut V)>
where Q: Hash + Equivalent<K>,
{
self.get_full_mut2_impl(key).map(|(i, k, v)| (i, &*k, v))
}
pub(crate) fn get_full_mut2_impl<Q: ?Sized>(&mut self, key: &Q)
-> Option<(usize, &mut K, &mut V)>
where Q: Hash + Equivalent<K>,
{
if let Some((_, found)) = self.find(key) {
let entry = &mut self.core.entries[found];
Some((found, &mut entry.key, &mut entry.value))
} else {
None
}
}
pub(crate) fn find<Q: ?Sized>(&self, key: &Q) -> Option<(usize, usize)>
where Q: Hash + Equivalent<K>,
{
if self.is_empty() { return None; }
let h = hash_elem_using(&self.hash_builder, key);
self.core.find_using(h, move |entry| { Q::equivalent(key, &entry.key) })
}
#[deprecated(note = "use `swap_remove`")]
pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
where Q: Hash + Equivalent<K>,
{
self.swap_remove(key)
}
pub fn swap_remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
where Q: Hash + Equivalent<K>,
{
self.swap_remove_full(key).map(third)
}
pub fn swap_remove_full<Q: ?Sized>(&mut self, key: &Q) -> Option<(usize, K, V)>
where Q: Hash + Equivalent<K>,
{
let (probe, found) = match self.find(key) {
None => return None,
Some(t) => t,
};
let (k, v) = self.core.swap_remove_found(probe, found);
Some((found, k, v))
}
pub fn shift_remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
where Q: Hash + Equivalent<K>,
{
self.shift_remove_full(key).map(third)
}
pub fn shift_remove_full<Q: ?Sized>(&mut self, key: &Q) -> Option<(usize, K, V)>
where Q: Hash + Equivalent<K>,
{
let (probe, found) = match self.find(key) {
None => return None,
Some(t) => t,
};
let (k, v) = self.core.shift_remove_found(probe, found);
Some((found, k, v))
}
pub fn pop(&mut self) -> Option<(K, V)> {
self.core.pop_impl()
}
pub fn retain<F>(&mut self, mut keep: F)
where F: FnMut(&K, &mut V) -> bool,
{
self.retain_mut(move |k, v| keep(k, v));
}
pub(crate) fn retain_mut<F>(&mut self, keep: F)
where F: FnMut(&mut K, &mut V) -> bool,
{
dispatch_32_vs_64!(self.retain_mut_sz::<_>(keep));
}
fn retain_mut_sz<Sz, F>(&mut self, keep: F)
where F: FnMut(&mut K, &mut V) -> bool,
Sz: Size,
{
self.core.retain_in_order_impl::<Sz, F>(keep);
}
pub fn sort_keys(&mut self)
where K: Ord,
{
self.core.sort_by(key_cmp)
}
pub fn sort_by<F>(&mut self, compare: F)
where F: FnMut(&K, &V, &K, &V) -> Ordering,
{
self.core.sort_by(compare)
}
pub fn sorted_by<F>(mut self, mut cmp: F) -> IntoIter<K, V>
where F: FnMut(&K, &V, &K, &V) -> Ordering
{
self.core.entries.sort_by(move |a, b| cmp(&a.key, &a.value, &b.key, &b.value));
self.into_iter()
}
pub fn drain(&mut self, range: RangeFull) -> Drain<K, V> {
self.core.clear_indices();
Drain {
iter: self.core.entries.drain(range),
}
}
}
fn key_cmp<K, V>(k1: &K, _v1: &V, k2: &K, _v2: &V) -> Ordering
where K: Ord
{
Ord::cmp(k1, k2)
}
impl<K, V, S> IndexMap<K, V, S> {
pub fn get_index(&self, index: usize) -> Option<(&K, &V)> {
self.core.entries.get(index).map(Bucket::refs)
}
pub fn get_index_mut(&mut self, index: usize) -> Option<(&mut K, &mut V)> {
self.core.entries.get_mut(index).map(Bucket::muts)
}
pub fn swap_remove_index(&mut self, index: usize) -> Option<(K, V)> {
let (probe, found) = match self.core.entries.get(index)
.map(|e| self.core.find_existing_entry(e))
{
None => return None,
Some(t) => t,
};
Some(self.core.swap_remove_found(probe, found))
}
pub fn shift_remove_index(&mut self, index: usize) -> Option<(K, V)> {
let (probe, found) = match self.core.entries.get(index)
.map(|e| self.core.find_existing_entry(e))
{
None => return None,
Some(t) => t,
};
Some(self.core.shift_remove_found(probe, found))
}
}
impl<K, V> OrderMapCore<K, V> {
fn len(&self) -> usize { self.entries.len() }
fn capacity(&self) -> usize {
usable_capacity(self.raw_capacity())
}
fn clear(&mut self) {
self.entries.clear();
self.clear_indices();
}
fn clear_indices(&mut self) {
for pos in self.indices.iter_mut() {
*pos = Pos::none();
}
}
fn first_allocation(&mut self) {
debug_assert_eq!(self.len(), 0);
let raw_cap = 8usize;
self.mask = raw_cap.wrapping_sub(1);
self.indices = vec![Pos::none(); raw_cap].into_boxed_slice();
self.entries = Vec::with_capacity(usable_capacity(raw_cap));
}
#[inline(never)]
fn double_capacity<Sz>(&mut self)
where Sz: Size
{
debug_assert!(self.raw_capacity() == 0 || self.len() > 0);
if self.raw_capacity() == 0 {
return self.first_allocation();
}
let mut first_ideal = 0;
for (i, index) in enumerate(&*self.indices) {
if let Some(pos) = index.pos() {
if 0 == probe_distance(self.mask, self.entries[pos].hash, i) {
first_ideal = i;
break;
}
}
}
let new_raw_cap = self.indices.len() * 2;
let old_indices = replace(&mut self.indices, vec![Pos::none(); new_raw_cap].into_boxed_slice());
self.mask = new_raw_cap.wrapping_sub(1);
for &pos in &old_indices[first_ideal..] {
dispatch_32_vs_64!(self.reinsert_entry_in_order::<Sz>(pos));
}
for &pos in &old_indices[..first_ideal] {
dispatch_32_vs_64!(self.reinsert_entry_in_order::<Sz>(pos));
}
let more = self.capacity() - self.len();
self.entries.reserve_exact(more);
}
fn reinsert_entry_in_order<SzNew, SzOld>(&mut self, pos: Pos)
where SzNew: Size,
SzOld: Size,
{
if let Some((i, hash_proxy)) = pos.resolve::<SzOld>() {
let entry_hash = if SzOld::is_same_size::<SzNew>() {
hash_proxy.get_short_hash(&self.entries, i).into_hash()
} else {
self.entries[i].hash
};
let mut probe = desired_pos(self.mask, entry_hash);
probe_loop!(probe < self.indices.len(), {
if self.indices[probe].is_none() {
self.indices[probe] = Pos::with_hash::<SzNew>(i, entry_hash);
return;
}
});
}
}
fn pop_impl(&mut self) -> Option<(K, V)> {
let (probe, found) = match self.entries.last()
.map(|e| self.find_existing_entry(e))
{
None => return None,
Some(t) => t,
};
debug_assert_eq!(found, self.entries.len() - 1);
Some(self.swap_remove_found(probe, found))
}
fn entry_phase_1<Sz>(&mut self, hash: HashValue, key: K) -> Entry<K, V>
where Sz: Size,
K: Eq,
{
let mut probe = desired_pos(self.mask, hash);
let mut dist = 0;
debug_assert!(self.len() < self.raw_capacity());
probe_loop!(probe < self.indices.len(), {
if let Some((i, hash_proxy)) = self.indices[probe].resolve::<Sz>() {
let entry_hash = hash_proxy.get_short_hash(&self.entries, i);
let their_dist = probe_distance(self.mask, entry_hash.into_hash(), probe);
if their_dist < dist {
return Entry::Vacant(VacantEntry {
map: self,
hash: hash,
key: key,
probe: probe,
});
} else if entry_hash == hash && self.entries[i].key == key {
return Entry::Occupied(OccupiedEntry {
map: self,
key: key,
probe: probe,
index: i,
});
}
} else {
return Entry::Vacant(VacantEntry {
map: self,
hash: hash,
key: key,
probe: probe,
});
}
dist += 1;
});
}
fn insert_phase_1<Sz>(&mut self, hash: HashValue, key: K, value: V) -> Inserted<V>
where Sz: Size,
K: Eq,
{
let mut probe = desired_pos(self.mask, hash);
let mut dist = 0;
let insert_kind;
debug_assert!(self.len() < self.raw_capacity());
probe_loop!(probe < self.indices.len(), {
let pos = &mut self.indices[probe];
if let Some((i, hash_proxy)) = pos.resolve::<Sz>() {
let entry_hash = hash_proxy.get_short_hash(&self.entries, i);
let their_dist = probe_distance(self.mask, entry_hash.into_hash(), probe);
if their_dist < dist {
let index = self.entries.len();
insert_kind = Inserted::RobinHood {
probe: probe,
old_pos: Pos::with_hash::<Sz>(index, hash),
};
break;
} else if entry_hash == hash && self.entries[i].key == key {
return Inserted::Swapped {
prev_value: replace(&mut self.entries[i].value, value),
};
}
} else {
let index = self.entries.len();
*pos = Pos::with_hash::<Sz>(index, hash);
insert_kind = Inserted::Done;
break;
}
dist += 1;
});
self.entries.push(Bucket { hash, key, value });
insert_kind
}
fn insert_phase_2<Sz>(&mut self, mut probe: usize, mut old_pos: Pos)
where Sz: Size
{
probe_loop!(probe < self.indices.len(), {
let pos = &mut self.indices[probe];
if pos.is_none() {
*pos = old_pos;
break;
} else {
old_pos = replace(pos, old_pos);
}
});
}
fn find_using<F>(&self, hash: HashValue, key_eq: F) -> Option<(usize, usize)>
where F: Fn(&Bucket<K, V>) -> bool,
{
dispatch_32_vs_64!(self.find_using_impl::<_>(hash, key_eq))
}
fn find_using_impl<Sz, F>(&self, hash: HashValue, key_eq: F) -> Option<(usize, usize)>
where F: Fn(&Bucket<K, V>) -> bool,
Sz: Size,
{
debug_assert!(self.len() > 0);
let mut probe = desired_pos(self.mask, hash);
let mut dist = 0;
probe_loop!(probe < self.indices.len(), {
if let Some((i, hash_proxy)) = self.indices[probe].resolve::<Sz>() {
let entry_hash = hash_proxy.get_short_hash(&self.entries, i);
if dist > probe_distance(self.mask, entry_hash.into_hash(), probe) {
return None;
} else if entry_hash == hash && key_eq(&self.entries[i]) {
return Some((probe, i));
}
} else {
return None;
}
dist += 1;
});
}
fn find_existing_entry(&self, entry: &Bucket<K, V>) -> (usize, usize)
{
debug_assert!(self.len() > 0);
let hash = entry.hash;
let actual_pos = ptrdistance(&self.entries[0], entry);
let probe = dispatch_32_vs_64!(self =>
find_existing_entry_at(&self.indices, hash, self.mask, actual_pos));
(probe, actual_pos)
}
fn shift_remove_found(&mut self, probe: usize, found: usize) -> (K, V) {
dispatch_32_vs_64!(self.shift_remove_found_impl(probe, found))
}
fn shift_remove_found_impl<Sz>(&mut self, probe: usize, found: usize) -> (K, V)
where Sz: Size
{
self.indices[probe] = Pos::none();
let entry = self.entries.remove(found);
if self.indices.len() < (self.entries.len() - found) * 2 {
for pos in self.indices.iter_mut() {
if let Some((i, _)) = pos.resolve::<Sz>() {
if i > found {
pos.set_pos::<Sz>(i - 1);
}
}
}
} else {
for (offset, entry) in enumerate(&self.entries[found..]) {
let index = found + offset;
let mut probe = desired_pos(self.mask, entry.hash);
probe_loop!(probe < self.indices.len(), {
let pos = &mut self.indices[probe];
if let Some((i, _)) = pos.resolve::<Sz>() {
if i == index + 1 {
pos.set_pos::<Sz>(index);
break;
}
}
});
}
}
self.backward_shift_after_removal::<Sz>(probe);
(entry.key, entry.value)
}
fn swap_remove_found(&mut self, probe: usize, found: usize) -> (K, V) {
dispatch_32_vs_64!(self.swap_remove_found_impl(probe, found))
}
fn swap_remove_found_impl<Sz>(&mut self, probe: usize, found: usize) -> (K, V)
where Sz: Size
{
self.indices[probe] = Pos::none();
let entry = self.entries.swap_remove(found);
if let Some(entry) = self.entries.get(found) {
let mut probe = desired_pos(self.mask, entry.hash);
probe_loop!(probe < self.indices.len(), {
let pos = &mut self.indices[probe];
if let Some((i, _)) = pos.resolve::<Sz>() {
if i >= self.entries.len() {
pos.set_pos::<Sz>(found);
break;
}
}
});
}
self.backward_shift_after_removal::<Sz>(probe);
(entry.key, entry.value)
}
fn backward_shift_after_removal<Sz>(&mut self, probe_at_remove: usize)
where Sz: Size
{
let mut last_probe = probe_at_remove;
let mut probe = probe_at_remove + 1;
probe_loop!(probe < self.indices.len(), {
if let Some((i, hash_proxy)) = self.indices[probe].resolve::<Sz>() {
let entry_hash = hash_proxy.get_short_hash(&self.entries, i);
if probe_distance(self.mask, entry_hash.into_hash(), probe) > 0 {
self.indices[last_probe] = self.indices[probe];
self.indices[probe] = Pos::none();
} else {
break;
}
} else {
break;
}
last_probe = probe;
});
}
fn retain_in_order_impl<Sz, F>(&mut self, mut keep: F)
where F: FnMut(&mut K, &mut V) -> bool,
Sz: Size,
{
let len = self.entries.len();
let mut n_deleted = 0;
for i in 0..len {
let will_keep;
let hash;
{
let ent = &mut self.entries[i];
hash = ent.hash;
will_keep = keep(&mut ent.key, &mut ent.value);
};
let probe = find_existing_entry_at::<Sz>(&self.indices, hash, self.mask, i);
if !will_keep {
n_deleted += 1;
self.indices[probe] = Pos::none();
self.backward_shift_after_removal::<Sz>(probe);
} else if n_deleted > 0 {
self.indices[probe].set_pos::<Sz>(i - n_deleted);
self.entries.swap(i - n_deleted, i);
}
}
self.entries.truncate(len - n_deleted);
}
fn sort_by<F>(&mut self, mut compare: F)
where F: FnMut(&K, &V, &K, &V) -> Ordering,
{
let side_index = self.save_hash_index();
self.entries.sort_by(move |ei, ej| compare(&ei.key, &ei.value, &ej.key, &ej.value));
self.restore_hash_index(side_index);
}
fn save_hash_index(&mut self) -> Vec<usize> {
Vec::from_iter(enumerate(&mut self.entries).map(|(i, elt)| {
replace(&mut elt.hash, HashValue(i)).get()
}))
}
fn restore_hash_index(&mut self, mut side_index: Vec<usize>) {
for (i, ent) in enumerate(&mut self.entries) {
let old_index = ent.hash.get();
ent.hash = HashValue(replace(&mut side_index[old_index], i));
}
dispatch_32_vs_64!(self => apply_new_index(&mut self.indices, &side_index));
fn apply_new_index<Sz>(indices: &mut [Pos], new_index: &[usize])
where Sz: Size
{
for pos in indices {
if let Some((i, _)) = pos.resolve::<Sz>() {
pos.set_pos::<Sz>(new_index[i]);
}
}
}
}
}
fn find_existing_entry_at<Sz>(indices: &[Pos], hash: HashValue,
mask: usize, entry_index: usize) -> usize
where Sz: Size,
{
let mut probe = desired_pos(mask, hash);
probe_loop!(probe < indices.len(), {
let i = indices[probe].resolve_existing_index::<Sz>();
if i == entry_index { return probe; }
});
}
use std::slice::Iter as SliceIter;
use std::slice::IterMut as SliceIterMut;
use std::vec::IntoIter as VecIntoIter;
pub struct Keys<'a, K: 'a, V: 'a> {
pub(crate) iter: SliceIter<'a, Bucket<K, V>>,
}
impl<'a, K, V> Iterator for Keys<'a, K, V> {
type Item = &'a K;
iterator_methods!(Bucket::key_ref);
}
impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> {
fn next_back(&mut self) -> Option<&'a K> {
self.iter.next_back().map(Bucket::key_ref)
}
}
impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
fn len(&self) -> usize {
self.iter.len()
}
}
impl<'a, K, V> Clone for Keys<'a, K, V> {
fn clone(&self) -> Keys<'a, K, V> {
Keys { iter: self.iter.clone() }
}
}
impl<'a, K: fmt::Debug, V> fmt::Debug for Keys<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list()
.entries(self.clone())
.finish()
}
}
pub struct Values<'a, K: 'a, V: 'a> {
iter: SliceIter<'a, Bucket<K, V>>,
}
impl<'a, K, V> Iterator for Values<'a, K, V> {
type Item = &'a V;
iterator_methods!(Bucket::value_ref);
}
impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(Bucket::value_ref)
}
}
impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
fn len(&self) -> usize {
self.iter.len()
}
}
impl<'a, K, V> Clone for Values<'a, K, V> {
fn clone(&self) -> Values<'a, K, V> {
Values { iter: self.iter.clone() }
}
}
impl<'a, K, V: fmt::Debug> fmt::Debug for Values<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list()
.entries(self.clone())
.finish()
}
}
pub struct ValuesMut<'a, K: 'a, V: 'a> {
iter: SliceIterMut<'a, Bucket<K, V>>,
}
impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
type Item = &'a mut V;
iterator_methods!(Bucket::value_mut);
}
impl<'a, K, V> DoubleEndedIterator for ValuesMut<'a, K, V> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(Bucket::value_mut)
}
}
impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> {
fn len(&self) -> usize {
self.iter.len()
}
}
pub struct Iter<'a, K: 'a, V: 'a> {
iter: SliceIter<'a, Bucket<K, V>>,
}
impl<'a, K, V> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
iterator_methods!(Bucket::refs);
}
impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(Bucket::refs)
}
}
impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
fn len(&self) -> usize {
self.iter.len()
}
}
impl<'a, K, V> Clone for Iter<'a, K, V> {
fn clone(&self) -> Iter<'a, K, V> {
Iter { iter: self.iter.clone() }
}
}
impl<'a, K: fmt::Debug, V: fmt::Debug> fmt::Debug for Iter<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list()
.entries(self.clone())
.finish()
}
}
pub struct IterMut<'a, K: 'a, V: 'a> {
iter: SliceIterMut<'a, Bucket<K, V>>,
}
impl<'a, K, V> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
iterator_methods!(Bucket::ref_mut);
}
impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(Bucket::ref_mut)
}
}
impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
fn len(&self) -> usize {
self.iter.len()
}
}
pub struct IntoIter<K, V> {
pub(crate) iter: VecIntoIter<Bucket<K, V>>,
}
impl<K, V> Iterator for IntoIter<K, V> {
type Item = (K, V);
iterator_methods!(Bucket::key_value);
}
impl<'a, K, V> DoubleEndedIterator for IntoIter<K, V> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(Bucket::key_value)
}
}
impl<K, V> ExactSizeIterator for IntoIter<K, V> {
fn len(&self) -> usize {
self.iter.len()
}
}
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IntoIter<K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let iter = self.iter.as_slice().iter().map(Bucket::refs);
f.debug_list().entries(iter).finish()
}
}
pub struct Drain<'a, K, V> where K: 'a, V: 'a {
pub(crate) iter: ::std::vec::Drain<'a, Bucket<K, V>>
}
impl<'a, K, V> Iterator for Drain<'a, K, V> {
type Item = (K, V);
iterator_methods!(Bucket::key_value);
}
impl<'a, K, V> DoubleEndedIterator for Drain<'a, K, V> {
double_ended_iterator_methods!(Bucket::key_value);
}
impl<'a, K, V, S> IntoIterator for &'a IndexMap<K, V, S>
where K: Hash + Eq,
S: BuildHasher,
{
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, K, V, S> IntoIterator for &'a mut IndexMap<K, V, S>
where K: Hash + Eq,
S: BuildHasher,
{
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<K, V, S> IntoIterator for IndexMap<K, V, S>
where K: Hash + Eq,
S: BuildHasher,
{
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
iter: self.core.entries.into_iter(),
}
}
}
use std::ops::{Index, IndexMut};
impl<'a, K, V, Q: ?Sized, S> Index<&'a Q> for IndexMap<K, V, S>
where Q: Hash + Equivalent<K>,
K: Hash + Eq,
S: BuildHasher,
{
type Output = V;
fn index(&self, key: &'a Q) -> &V {
if let Some(v) = self.get(key) {
v
} else {
panic!("IndexMap: key not found")
}
}
}
impl<'a, K, V, Q: ?Sized, S> IndexMut<&'a Q> for IndexMap<K, V, S>
where Q: Hash + Equivalent<K>,
K: Hash + Eq,
S: BuildHasher,
{
fn index_mut(&mut self, key: &'a Q) -> &mut V {
if let Some(v) = self.get_mut(key) {
v
} else {
panic!("IndexMap: key not found")
}
}
}
impl<K, V, S> FromIterator<(K, V)> for IndexMap<K, V, S>
where K: Hash + Eq,
S: BuildHasher + Default,
{
fn from_iter<I: IntoIterator<Item=(K, V)>>(iterable: I) -> Self {
let iter = iterable.into_iter();
let (low, _) = iter.size_hint();
let mut map = Self::with_capacity_and_hasher(low, <_>::default());
map.extend(iter);
map
}
}
impl<K, V, S> Extend<(K, V)> for IndexMap<K, V, S>
where K: Hash + Eq,
S: BuildHasher,
{
fn extend<I: IntoIterator<Item=(K, V)>>(&mut self, iterable: I) {
for (k, v) in iterable { self.insert(k, v); }
}
}
impl<'a, K, V, S> Extend<(&'a K, &'a V)> for IndexMap<K, V, S>
where K: Hash + Eq + Copy,
V: Copy,
S: BuildHasher,
{
fn extend<I: IntoIterator<Item=(&'a K, &'a V)>>(&mut self, iterable: I) {
self.extend(iterable.into_iter().map(|(&key, &value)| (key, value)));
}
}
impl<K, V, S> Default for IndexMap<K, V, S>
where S: BuildHasher + Default,
{
fn default() -> Self {
Self::with_capacity_and_hasher(0, S::default())
}
}
impl<K, V1, S1, V2, S2> PartialEq<IndexMap<K, V2, S2>> for IndexMap<K, V1, S1>
where K: Hash + Eq,
V1: PartialEq<V2>,
S1: BuildHasher,
S2: BuildHasher
{
fn eq(&self, other: &IndexMap<K, V2, S2>) -> bool {
if self.len() != other.len() {
return false;
}
self.iter().all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
}
}
impl<K, V, S> Eq for IndexMap<K, V, S>
where K: Eq + Hash,
V: Eq,
S: BuildHasher
{
}
#[cfg(test)]
mod tests {
use super::*;
use util::enumerate;
#[test]
fn it_works() {
let mut map = IndexMap::new();
assert_eq!(map.is_empty(), true);
map.insert(1, ());
map.insert(1, ());
assert_eq!(map.len(), 1);
assert!(map.get(&1).is_some());
assert_eq!(map.is_empty(), false);
}
#[test]
fn new() {
let map = IndexMap::<String, String>::new();
println!("{:?}", map);
assert_eq!(map.capacity(), 0);
assert_eq!(map.len(), 0);
assert_eq!(map.is_empty(), true);
}
#[test]
fn insert() {
let insert = [0, 4, 2, 12, 8, 7, 11, 5];
let not_present = [1, 3, 6, 9, 10];
let mut map = IndexMap::with_capacity(insert.len());
for (i, &elt) in enumerate(&insert) {
assert_eq!(map.len(), i);
map.insert(elt, elt);
assert_eq!(map.len(), i + 1);
assert_eq!(map.get(&elt), Some(&elt));
assert_eq!(map[&elt], elt);
}
println!("{:?}", map);
for &elt in ¬_present {
assert!(map.get(&elt).is_none());
}
}
#[test]
fn insert_full() {
let insert = vec![9, 2, 7, 1, 4, 6, 13];
let present = vec![1, 6, 2];
let mut map = IndexMap::with_capacity(insert.len());
for (i, &elt) in enumerate(&insert) {
assert_eq!(map.len(), i);
let (index, existing) = map.insert_full(elt, elt);
assert_eq!(existing, None);
assert_eq!(Some(index), map.get_full(&elt).map(|x| x.0));
assert_eq!(map.len(), i + 1);
}
let len = map.len();
for &elt in &present {
let (index, existing) = map.insert_full(elt, elt);
assert_eq!(existing, Some(elt));
assert_eq!(Some(index), map.get_full(&elt).map(|x| x.0));
assert_eq!(map.len(), len);
}
}
#[test]
fn insert_2() {
let mut map = IndexMap::with_capacity(16);
let mut keys = vec![];
keys.extend(0..16);
keys.extend(128..267);
for &i in &keys {
let old_map = map.clone();
map.insert(i, ());
for key in old_map.keys() {
if map.get(key).is_none() {
println!("old_map: {:?}", old_map);
println!("map: {:?}", map);
panic!("did not find {} in map", key);
}
}
}
for &i in &keys {
assert!(map.get(&i).is_some(), "did not find {}", i);
}
}
#[test]
fn insert_order() {
let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
let mut map = IndexMap::new();
for &elt in &insert {
map.insert(elt, ());
}
assert_eq!(map.keys().count(), map.len());
assert_eq!(map.keys().count(), insert.len());
for (a, b) in insert.iter().zip(map.keys()) {
assert_eq!(a, b);
}
for (i, k) in (0..insert.len()).zip(map.keys()) {
assert_eq!(map.get_index(i).unwrap().0, k);
}
}
#[test]
fn grow() {
let insert = [0, 4, 2, 12, 8, 7, 11];
let not_present = [1, 3, 6, 9, 10];
let mut map = IndexMap::with_capacity(insert.len());
for (i, &elt) in enumerate(&insert) {
assert_eq!(map.len(), i);
map.insert(elt, elt);
assert_eq!(map.len(), i + 1);
assert_eq!(map.get(&elt), Some(&elt));
assert_eq!(map[&elt], elt);
}
println!("{:?}", map);
for &elt in &insert {
map.insert(elt * 10, elt);
}
for &elt in &insert {
map.insert(elt * 100, elt);
}
for (i, &elt) in insert.iter().cycle().enumerate().take(100) {
map.insert(elt * 100 + i as i32, elt);
}
println!("{:?}", map);
for &elt in ¬_present {
assert!(map.get(&elt).is_none());
}
}
#[test]
fn remove() {
let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
let mut map = IndexMap::new();
for &elt in &insert {
map.insert(elt, elt);
}
assert_eq!(map.keys().count(), map.len());
assert_eq!(map.keys().count(), insert.len());
for (a, b) in insert.iter().zip(map.keys()) {
assert_eq!(a, b);
}
let remove_fail = [99, 77];
let remove = [4, 12, 8, 7];
for &key in &remove_fail {
assert!(map.swap_remove_full(&key).is_none());
}
println!("{:?}", map);
for &key in &remove {
let index = map.get_full(&key).unwrap().0;
assert_eq!(map.swap_remove_full(&key), Some((index, key, key)));
}
println!("{:?}", map);
for key in &insert {
assert_eq!(map.get(key).is_some(), !remove.contains(key));
}
assert_eq!(map.len(), insert.len() - remove.len());
assert_eq!(map.keys().count(), insert.len() - remove.len());
}
#[test]
fn remove_to_empty() {
let mut map = indexmap! { 0 => 0, 4 => 4, 5 => 5 };
map.swap_remove(&5).unwrap();
map.swap_remove(&4).unwrap();
map.swap_remove(&0).unwrap();
assert!(map.is_empty());
}
#[test]
fn swap_remove_index() {
let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
let mut map = IndexMap::new();
for &elt in &insert {
map.insert(elt, elt * 2);
}
let mut vector = insert.to_vec();
let remove_sequence = &[3, 3, 10, 4, 5, 4, 3, 0, 1];
for &rm in remove_sequence {
let out_vec = vector.swap_remove(rm);
let (out_map, _) = map.swap_remove_index(rm).unwrap();
assert_eq!(out_vec, out_map);
}
assert_eq!(vector.len(), map.len());
for (a, b) in vector.iter().zip(map.keys()) {
assert_eq!(a, b);
}
}
#[test]
fn partial_eq_and_eq() {
let mut map_a = IndexMap::new();
map_a.insert(1, "1");
map_a.insert(2, "2");
let mut map_b = map_a.clone();
assert_eq!(map_a, map_b);
map_b.swap_remove(&1);
assert_ne!(map_a, map_b);
let map_c: IndexMap<_, String> = map_b.into_iter().map(|(k, v)| (k, v.to_owned())).collect();
assert_ne!(map_a, map_c);
assert_ne!(map_c, map_a);
}
#[test]
fn extend() {
let mut map = IndexMap::new();
map.extend(vec![(&1, &2), (&3, &4)]);
map.extend(vec![(5, 6)]);
assert_eq!(map.into_iter().collect::<Vec<_>>(), vec![(1, 2), (3, 4), (5, 6)]);
}
#[test]
fn entry() {
let mut map = IndexMap::new();
map.insert(1, "1");
map.insert(2, "2");
{
let e = map.entry(3);
assert_eq!(e.index(), 2);
let e = e.or_insert("3");
assert_eq!(e, &"3");
}
let e = map.entry(2);
assert_eq!(e.index(), 1);
assert_eq!(e.key(), &2);
match e {
Entry::Occupied(ref e) => assert_eq!(e.get(), &"2"),
Entry::Vacant(_) => panic!()
}
assert_eq!(e.or_insert("4"), &"2");
}
#[test]
fn entry_and_modify() {
let mut map = IndexMap::new();
map.insert(1, "1");
map.entry(1).and_modify(|x| *x = "2");
assert_eq!(Some(&"2"), map.get(&1));
map.entry(2).and_modify(|x| *x = "doesn't exist");
assert_eq!(None, map.get(&2));
}
#[test]
fn entry_or_default() {
let mut map = IndexMap::new();
#[derive(Debug, PartialEq)]
enum TestEnum {
DefaultValue,
NonDefaultValue,
}
impl Default for TestEnum {
fn default() -> Self {
TestEnum::DefaultValue
}
}
map.insert(1, TestEnum::NonDefaultValue);
assert_eq!(&mut TestEnum::NonDefaultValue, map.entry(1).or_default());
assert_eq!(&mut TestEnum::DefaultValue, map.entry(2).or_default());
}
#[test]
fn keys() {
let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
let map: IndexMap<_, _> = vec.into_iter().collect();
let keys: Vec<_> = map.keys().cloned().collect();
assert_eq!(keys.len(), 3);
assert!(keys.contains(&1));
assert!(keys.contains(&2));
assert!(keys.contains(&3));
}
#[test]
fn values() {
let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
let map: IndexMap<_, _> = vec.into_iter().collect();
let values: Vec<_> = map.values().cloned().collect();
assert_eq!(values.len(), 3);
assert!(values.contains(&'a'));
assert!(values.contains(&'b'));
assert!(values.contains(&'c'));
}
#[test]
fn values_mut() {
let vec = vec![(1, 1), (2, 2), (3, 3)];
let mut map: IndexMap<_, _> = vec.into_iter().collect();
for value in map.values_mut() {
*value *= 2
}
let values: Vec<_> = map.values().cloned().collect();
assert_eq!(values.len(), 3);
assert!(values.contains(&2));
assert!(values.contains(&4));
assert!(values.contains(&6));
}
}