use indexmap::{IndexMap, IndexSet}; use itertools::Itertools;
use quickcheck::Arbitrary; use quickcheck::Gen; use quickcheck::QuickCheck; use quickcheck::TestResult;
use fnv::FnvHasher; use std::hash::{BuildHasher, BuildHasherDefault}; type FnvBuilder = BuildHasherDefault<FnvHasher>; type IndexMapFnv<K, V> = IndexMap<K, V, FnvBuilder>;
use std::cmp::min; use std::collections::HashMap; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; use std::ops::Bound; use std::ops::Deref;
use indexmap::map::Entry; use std::collections::hash_map::Entry as StdEntry;
fn with_cap(template: Vec<()>) -> bool { let cap = template.len(); let map: IndexMap<u8, u8> = IndexMap::with_capacity(cap);
println!("wish: {}, got: {} (diff: {})", cap, map.capacity(), map.capacity() as isize - cap as isize);
map.capacity() >= cap
}
fn drain_full(insert: Vec<u8>) -> bool { letmut map = IndexMap::new(); for &key in &insert {
map.insert(key, ());
} letmut clone = map.clone(); let drained = clone.drain(..); for (key, _) in drained {
map.swap_remove(&key);
}
map.is_empty()
}
// First see if `Vec::drain` is happy with this range. let result = std::panic::catch_unwind(|| { letmut keys: Vec<u8> = map.keys().copied().collect();
keys.drain(range);
keys
});
iflet Ok(keys) = result {
map.drain(range); // Check that our `drain` matches the same key order.
assert!(map.keys().eq(&keys)); // Check that hash lookups all work too.
assert!(keys.iter().all(|key| map.contains_key(key)));
TestResult::passed()
} else { // If `Vec::drain` panicked, so should we.
TestResult::must_fail(move || { map.drain(range); })
}
}
fn shift_remove(insert: Vec<u8>, remove: Vec<u8>) -> bool { letmut map = IndexMap::new(); for &key in &insert {
map.insert(key, ());
} for &key in &remove {
map.shift_remove(&key);
} let elements = &set(&insert) - &set(&remove);
// Check that order is preserved after removals letmut iter = map.keys(); for &key in insert.iter().unique() { if elements.contains(&key) {
assert_eq!(Some(&key), iter.next());
}
}
set.iter().enumerate().all(|(i, &key)| { let value = key & !1;
map[&key] == value && map[i] == value
})
}
// Use `u8` test indices so quickcheck is less likely to go out of bounds. fn set_swap_indices(vec: Vec<u8>, a: u8, b: u8) -> TestResult { letmut set = IndexSet::<u8>::from_iter(vec); let a = usize::from(a); let b = usize::from(b);
if a >= set.len() || b >= set.len() { return TestResult::discard();
}
// Check both iteration order and hash lookups
assert!(set.iter().eq(vec.iter()));
assert!(vec.iter().enumerate().all(|(i, x)| {
set.get_index_of(x) == Some(i)
}));
TestResult::passed()
}
fn map_swap_indices(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
test_map_swap_indices(vec, from, to, IndexMap::swap_indices)
}
fn occupied_entry_swap_indices(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
test_map_swap_indices(vec, from, to, |map, from, to| { let key = map.keys()[from]; match map.entry(key) {
Entry::Occupied(entry) => entry.swap_indices(to),
_ => unreachable!(),
}
})
}
fn indexed_entry_swap_indices(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
test_map_swap_indices(vec, from, to, |map, from, to| {
map.get_index_entry(from).unwrap().swap_indices(to);
})
}
fn raw_occupied_entry_swap_indices(vec: Vec<u8>, from: u8, to: u8) -> TestResult { use indexmap::map::raw_entry_v1::{RawEntryApiV1, RawEntryMut};
test_map_swap_indices(vec, from, to, |map, from, to| { let key = map.keys()[from]; match map.raw_entry_mut_v1().from_key(&key) {
RawEntryMut::Occupied(entry) => entry.swap_indices(to),
_ => unreachable!(),
}
})
}
// Use `u8` test indices so quickcheck is less likely to go out of bounds. fn set_move_index(vec: Vec<u8>, from: u8, to: u8) -> TestResult { letmut set = IndexSet::<u8>::from_iter(vec); let from = usize::from(from); let to = usize::from(to);
if from >= set.len() || to >= set.len() { return TestResult::discard();
}
letmut vec = Vec::from_iter(set.iter().cloned()); let x = vec.remove(from);
vec.insert(to, x);
set.move_index(from, to);
// Check both iteration order and hash lookups
assert!(set.iter().eq(vec.iter()));
assert!(vec.iter().enumerate().all(|(i, x)| {
set.get_index_of(x) == Some(i)
}));
TestResult::passed()
}
fn map_move_index(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
test_map_move_index(vec, from, to, IndexMap::move_index)
}
fn occupied_entry_move_index(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
test_map_move_index(vec, from, to, |map, from, to| { let key = map.keys()[from]; match map.entry(key) {
Entry::Occupied(entry) => entry.move_index(to),
_ => unreachable!(),
}
})
}
fn indexed_entry_move_index(vec: Vec<u8>, from: u8, to: u8) -> TestResult {
test_map_move_index(vec, from, to, |map, from, to| {
map.get_index_entry(from).unwrap().move_index(to);
})
}
fn raw_occupied_entry_move_index(vec: Vec<u8>, from: u8, to: u8) -> TestResult { use indexmap::map::raw_entry_v1::{RawEntryApiV1, RawEntryMut};
test_map_move_index(vec, from, to, |map, from, to| { let key = map.keys()[from]; match map.raw_entry_mut_v1().from_key(&key) {
RawEntryMut::Occupied(entry) => entry.move_index(to),
_ => unreachable!(),
}
})
}
fn occupied_entry_shift_insert(vec: Vec<u8>, i: u8) -> TestResult {
test_map_shift_insert(vec, i, |map, i, key| { match map.entry(key) {
Entry::Vacant(entry) => entry.shift_insert(i, ()),
_ => unreachable!(),
};
})
}
fn raw_occupied_entry_shift_insert(vec: Vec<u8>, i: u8) -> TestResult { use indexmap::map::raw_entry_v1::{RawEntryApiV1, RawEntryMut};
test_map_shift_insert(vec, i, |map, i, key| { match map.raw_entry_mut_v1().from_key(&key) {
RawEntryMut::Vacant(entry) => entry.shift_insert(i, key, ()),
_ => unreachable!(),
};
})
}
}
fn test_map_swap_indices<F>(vec: Vec<u8>, a: u8, b: u8, swap_indices: F) -> TestResult where
F: FnOnce(&mut IndexMap<u8, ()>, usize, usize),
{ letmut map = IndexMap::<u8, ()>::from_iter(vec.into_iter().map(|k| (k, ()))); let a = usize::from(a); let b = usize::from(b);
if a >= map.len() || b >= map.len() { return TestResult::discard();
}
fn retain_ordered(keys: Large<Vec<i8>>, remove: Large<Vec<i8>>) -> () { letmut map = indexmap(keys.iter()); let initial_map = map.clone(); // deduplicated in-order input let remove_map = indexmap(remove.iter()); let keys_s = set(keys.iter()); let remove_s = set(remove.iter()); let answer = &keys_s - &remove_s;
map.retain(|k, _| !remove_map.contains_key(k));
// check the values
assert_eq!(map.len(), answer.len()); for key in &answer {
assert!(map.contains_key(key));
} // check the order
itertools::assert_equal(map.keys(), initial_map.keys().filter(|&k| !remove_map.contains_key(k)));
}
// reverse dedup: Because IndexMap::from_iter keeps the last value for // identical keys
answer.reverse();
answer.dedup_by_key(|t| t.0);
answer.reverse();
map.sort_by(|k1, _, k2, _| Ord::cmp(k1, k2));
// check it contains all the values it should for &(key, val) in &answer {
assert_eq!(map[&key], val);
}
// check the order
let mapv = Vec::from_iter(map);
assert_eq!(answer, mapv);
fn generate_answer(input: &Vec<(i8, i8)>) -> Vec<(i8, i8)> { // to mimic what `IndexMap::from_iter` does: // need to get (A) the unique keys in forward order, and (B) the // last value of each of those keys.
// create (A): an iterable that yields the unique keys in ltr order letmut seen_keys = HashSet::new(); let unique_keys_forward = input.iter().filter_map(move |(k, _)| { if seen_keys.contains(k) { None } else { seen_keys.insert(*k); Some(*k) }
});
// create (B): a mapping of keys to the last value seen for that key // this is the same as reversing the input and taking the first // value seen for that key! letmut last_val_per_key = HashMap::new(); for &(k, v) in input.iter().rev() { if !last_val_per_key.contains_key(&k) {
last_val_per_key.insert(k, v);
}
}
// iterate over the keys in (A) in order, and match each one with // the corresponding last value from (B) letmut ans: Vec<_> = unique_keys_forward
.map(|k| (k, *last_val_per_key.get(&k).unwrap()))
.collect();
// finally, since this test is testing `.reverse()`, reverse the // answer in-place
ans.reverse();
ans
}
let answer = generate_answer(&keyvals.0);
// perform the work
map.reverse();
// check it contains all the values it should for &(key, val) in &answer {
assert_eq!(map[&key], val);
}
// check the order let mapv = Vec::from_iter(map);
assert_eq!(answer, mapv);
}
}
fn assert_sorted_by_key<I, Key, X>(iterable: I, key: Key) where
I: IntoIterator,
I::Item: Ord + Clone + Debug,
Key: Fn(&I::Item) -> X,
X: Ord,
{ let input = Vec::from_iter(iterable); letmut sorted = input.clone();
sorted.sort_by_key(key);
assert_eq!(input, sorted);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.