diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..a9d37c56 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/src/lib.rs b/src/lib.rs index afed023f..957b7dfb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ use std::hash::BuildHasher; use std::hash::Hasher; use std::collections::hash_map::RandomState; use std::borrow::Borrow; +use std::ops::RangeFull; use std::cmp::{max, Ordering}; use std::fmt; @@ -979,6 +980,17 @@ impl OrderMap self.entries.sort_by(move |a, b| cmp(&a.key, &a.value, &b.key, &b.value)); self.into_iter() } + /// Clears the `OrderMap`, returning all key-value pairs as a drain iterator. + /// Keeps the allocated memory for reuse. + pub fn drain(&mut self, range: RangeFull) -> Drain { + for i in &mut self.indices { + *i = Pos::none(); + } + + Drain { + inner: self.entries.drain(range), + } + } } impl OrderMap { @@ -1496,6 +1508,20 @@ impl Eq for OrderMap { } +pub struct Drain<'a, K, V> where K: 'a, V: 'a { + inner: ::std::vec::Drain<'a, Bucket> +} + +impl<'a, K, V> Iterator for Drain<'a, K, V> { + type Item = (K, V); + fn next(&mut self) -> Option { + self.inner.next().map(|bucket| (bucket.key, bucket.value)) + } + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/tests/quick.rs b/tests/quick.rs index 239918ab..98192906 100644 --- a/tests/quick.rs +++ b/tests/quick.rs @@ -105,6 +105,18 @@ quickcheck! { map.capacity() >= cap } + fn drain(insert: Vec) -> bool { + let mut map = OrderMap::new(); + for &key in &insert { + map.insert(key, ()); + } + let mut clone = map.clone(); + let drained = clone.drain(..); + for (key, _) in drained { + map.remove(&key); + } + map.is_empty() + } } use Op::*;