Skip to content

Commit

Permalink
Adds a OrderMap::drain() method
Browse files Browse the repository at this point in the history
Problem:
Porting some code that used HashMap's drain to OrderMap revealed a small
API gap.

Solution:
Added a drain method, mostly mirroring what std::collections::HashMap
offers except returning a standard Vec instead of a Drain.

drain() provides an efficient way to remove all values without shrinking
the capacity of the original OrderMap.

Validation:
Added unit tests and ported an existing HashMap::drain() user to
OrderMap::drain
  • Loading branch information
Steve Jenson committed Apr 20, 2017
1 parent dc0be46 commit 0e18ddc
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
target
Cargo.lock
43 changes: 43 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,14 @@ impl<K, V, S> OrderMap<K, V, S>
pub fn capacity(&self) -> usize {
usable_capacity(self.raw_capacity())
}

/// Clears the `OrderMap`, returning all key-value pairs as a `Vec`.
/// Keeps the allocated memory for reuse.
pub fn drain(&mut self) -> Vec<(K, V)> {
let cap = self.indices.capacity();
replace(&mut self.indices, vec![Pos::none(); cap]);
self.entries.drain(..).map(|bucket| (bucket.key, bucket.value)).collect()
}
}

/// Trait for the "size class". Either u32 or u64 depending on the index
Expand Down Expand Up @@ -1690,4 +1698,39 @@ mod tests {
assert_ne!(map_a, map_c);
assert_ne!(map_c, map_a);
}


#[test]
fn drain_basic() {
let mut map_a = OrderMap::new();
map_a.insert(1, "1");
map_a.insert(2, "2");
let entries = map_a.drain();
assert!(map_a.is_empty());
assert_eq!(entries.len(), 2);
assert!(map_a.is_empty());

map_a.insert(3, "3");
assert!(!map_a.is_empty());
assert_eq!(map_a.len(), 1);
assert!(map_a.get(&3).is_some());
assert!(map_a.get(&1).is_none());
}

#[test]
fn drain_after_resize() {
let mut map_a = OrderMap::with_capacity(2);
map_a.insert(1, "1");
map_a.insert(2, "2");
map_a.insert(3, "3");
let entries = map_a.drain();
assert!(map_a.is_empty());
assert_eq!(entries.len(), 3);

map_a.insert(4, "4");
assert!(!map_a.is_empty());
assert_eq!(map_a.len(), 1);
assert!(map_a.get(&4).is_some());
assert!(map_a.get(&1).is_none());
}
}

0 comments on commit 0e18ddc

Please sign in to comment.