Merge pull request #4571 from thestinger/container
more work on container traits
This commit is contained in:
commit
e02449c41d
@ -10,7 +10,46 @@
|
||||
|
||||
//! Container traits
|
||||
|
||||
pub trait Set<T> {
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
pub trait Container {
|
||||
/// Return the number of elements in the container
|
||||
pure fn len(&self) -> uint;
|
||||
|
||||
/// Return true if the container contains no elements
|
||||
pure fn is_empty(&self) -> bool;
|
||||
}
|
||||
|
||||
pub trait Mutable: Container {
|
||||
/// Clear the container, removing all values.
|
||||
fn clear(&mut self);
|
||||
}
|
||||
|
||||
pub trait Map<K, V>: Mutable {
|
||||
/// Return true if the map contains a value for the specified key
|
||||
pure fn contains_key(&self, key: &K) -> bool;
|
||||
|
||||
/// Visit all key-value pairs
|
||||
pure fn each(&self, f: fn(&K, &V) -> bool);
|
||||
|
||||
/// Visit all keys
|
||||
pure fn each_key(&self, f: fn(&K) -> bool);
|
||||
|
||||
/// Visit all values
|
||||
pure fn each_value(&self, f: fn(&V) -> bool);
|
||||
|
||||
/// Insert a key-value pair into the map. An existing value for a
|
||||
/// key is replaced by the new value. Return true if the key did
|
||||
/// not already exist in the map.
|
||||
fn insert(&mut self, key: K, value: V) -> bool;
|
||||
|
||||
/// Remove a key-value pair from the map. Return true if the key
|
||||
/// was present in the map, otherwise false.
|
||||
fn remove(&mut self, key: &K) -> bool;
|
||||
}
|
||||
|
||||
pub trait Set<T>: Mutable {
|
||||
/// Return true if the set contains a value
|
||||
pure fn contains(&self, value: &T) -> bool;
|
||||
|
||||
|
@ -23,31 +23,10 @@ use hash::Hash;
|
||||
use prelude::*;
|
||||
use to_bytes::IterBytes;
|
||||
|
||||
pub trait SendMap<K:Eq Hash, V: Copy> {
|
||||
// FIXME(#3148) ^^^^ once find_ref() works, we can drop V:copy
|
||||
|
||||
fn insert(&mut self, k: K, +v: V) -> bool;
|
||||
fn remove(&mut self, k: &K) -> bool;
|
||||
fn pop(&mut self, k: &K) -> Option<V>;
|
||||
fn swap(&mut self, k: K, +v: V) -> Option<V>;
|
||||
fn consume(&mut self, f: fn(K, V));
|
||||
fn clear(&mut self);
|
||||
pure fn len(&const self) -> uint;
|
||||
pure fn is_empty(&const self) -> bool;
|
||||
pure fn contains_key(&const self, k: &K) -> bool;
|
||||
pure fn each(&self, blk: fn(k: &K, v: &V) -> bool);
|
||||
pure fn each_key_ref(&self, blk: fn(k: &K) -> bool);
|
||||
pure fn each_value_ref(&self, blk: fn(v: &V) -> bool);
|
||||
pure fn find(&const self, k: &K) -> Option<V>;
|
||||
pure fn get(&const self, k: &K) -> V;
|
||||
pure fn find_ref(&self, k: &K) -> Option<&self/V>;
|
||||
pure fn get_ref(&self, k: &K) -> &self/V;
|
||||
}
|
||||
|
||||
/// Open addressing with linear probing.
|
||||
pub mod linear {
|
||||
use iter::BaseIter;
|
||||
use container::Set;
|
||||
use container::{Container, Mutable, Map, Set};
|
||||
use cmp::Eq;
|
||||
use cmp;
|
||||
use hash::Hash;
|
||||
@ -279,7 +258,48 @@ pub mod linear {
|
||||
}
|
||||
}
|
||||
|
||||
impl<K:Hash IterBytes Eq,V> LinearMap<K,V> {
|
||||
impl <K: Hash IterBytes Eq, V> LinearMap<K, V>: Container {
|
||||
pure fn len(&self) -> uint { self.size }
|
||||
pure fn is_empty(&self) -> bool { self.len() == 0 }
|
||||
}
|
||||
|
||||
impl <K: Hash IterBytes Eq, V> LinearMap<K, V>: Mutable {
|
||||
fn clear(&mut self) {
|
||||
for uint::range(0, self.buckets.len()) |idx| {
|
||||
self.buckets[idx] = None;
|
||||
}
|
||||
self.size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
impl <K: Hash IterBytes Eq, V> LinearMap<K, V>: Map<K, V> {
|
||||
pure fn contains_key(&self, k: &K) -> bool {
|
||||
match self.bucket_for_key(self.buckets, k) {
|
||||
FoundEntry(_) => {true}
|
||||
TableFull | FoundHole(_) => {false}
|
||||
}
|
||||
}
|
||||
|
||||
pure fn each(&self, blk: fn(k: &K, v: &V) -> bool) {
|
||||
for vec::each(self.buckets) |slot| {
|
||||
let mut broke = false;
|
||||
do slot.iter |bucket| {
|
||||
if !blk(&bucket.key, &bucket.value) {
|
||||
broke = true; // FIXME(#3064) just write "break;"
|
||||
}
|
||||
}
|
||||
if broke { break; }
|
||||
}
|
||||
}
|
||||
|
||||
pure fn each_key(&self, blk: fn(k: &K) -> bool) {
|
||||
self.each(|k, _v| blk(k))
|
||||
}
|
||||
|
||||
pure fn each_value(&self, blk: fn(v: &V) -> bool) {
|
||||
self.each(|_k, v| blk(v))
|
||||
}
|
||||
|
||||
fn insert(&mut self, k: K, v: V) -> bool {
|
||||
if self.size >= self.resize_at {
|
||||
// n.b.: We could also do this after searching, so
|
||||
@ -301,7 +321,9 @@ pub mod linear {
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K:Hash IterBytes Eq,V> LinearMap<K,V> {
|
||||
fn pop(&mut self, k: &K) -> Option<V> {
|
||||
let hash = k.hash_keyed(self.k0, self.k1) as uint;
|
||||
self.pop_internal(hash, k)
|
||||
@ -347,29 +369,6 @@ pub mod linear {
|
||||
}
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
for uint::range(0, self.buckets.len()) |idx| {
|
||||
self.buckets[idx] = None;
|
||||
}
|
||||
self.size = 0;
|
||||
}
|
||||
|
||||
pure fn len(&const self) -> uint {
|
||||
self.size
|
||||
}
|
||||
|
||||
pure fn is_empty(&const self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
pure fn contains_key(&const self,
|
||||
k: &K) -> bool {
|
||||
match self.bucket_for_key(self.buckets, k) {
|
||||
FoundEntry(_) => {true}
|
||||
TableFull | FoundHole(_) => {false}
|
||||
}
|
||||
}
|
||||
|
||||
pure fn find_ref(&self, k: &K) -> Option<&self/V> {
|
||||
match self.bucket_for_key(self.buckets, k) {
|
||||
FoundEntry(idx) => {
|
||||
@ -396,26 +395,6 @@ pub mod linear {
|
||||
None => fail fmt!("No entry found for key: %?", k),
|
||||
}
|
||||
}
|
||||
|
||||
pure fn each(&self, blk: fn(k: &K, v: &V) -> bool) {
|
||||
for vec::each(self.buckets) |slot| {
|
||||
let mut broke = false;
|
||||
do slot.iter |bucket| {
|
||||
if !blk(&bucket.key, &bucket.value) {
|
||||
broke = true; // FIXME(#3064) just write "break;"
|
||||
}
|
||||
}
|
||||
if broke { break; }
|
||||
}
|
||||
}
|
||||
|
||||
pure fn each_key(&self, blk: fn(k: &K) -> bool) {
|
||||
self.each(|k, _v| blk(k))
|
||||
}
|
||||
|
||||
pure fn each_value(&self, blk: fn(v: &V) -> bool) {
|
||||
self.each(|_k, v| blk(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<K:Hash IterBytes Eq, V: Copy> LinearMap<K,V> {
|
||||
@ -482,6 +461,15 @@ pub mod linear {
|
||||
}
|
||||
}
|
||||
|
||||
impl <T: Hash IterBytes Eq> LinearSet<T>: Container {
|
||||
pure fn len(&self) -> uint { self.map.len() }
|
||||
pure fn is_empty(&self) -> bool { self.map.is_empty() }
|
||||
}
|
||||
|
||||
impl <T: Hash IterBytes Eq> LinearSet<T>: Mutable {
|
||||
fn clear(&mut self) { self.map.clear() }
|
||||
}
|
||||
|
||||
impl <T: Hash IterBytes Eq> LinearSet<T>: Set<T> {
|
||||
/// Return true if the set contains a value
|
||||
pure fn contains(&self, value: &T) -> bool {
|
||||
@ -500,12 +488,6 @@ pub mod linear {
|
||||
impl <T: Hash IterBytes Eq> LinearSet<T> {
|
||||
/// Create an empty LinearSet
|
||||
static fn new() -> LinearSet<T> { LinearSet{map: LinearMap()} }
|
||||
|
||||
/// Return the number of elements in the set
|
||||
pure fn len(&self) -> uint { self.map.len() }
|
||||
|
||||
/// Return true if the set contains no elements
|
||||
pure fn is_empty(&self) -> bool { self.map.is_empty() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
//! A priority queue implemented with a binary heap
|
||||
|
||||
use core::container::{Container, Mutable};
|
||||
use core::cmp::Ord;
|
||||
use core::prelude::*;
|
||||
use core::ptr::addr_of;
|
||||
@ -24,6 +25,19 @@ pub struct PriorityQueue <T: Ord>{
|
||||
priv data: ~[T],
|
||||
}
|
||||
|
||||
impl <T: Ord> PriorityQueue<T>: Container {
|
||||
/// Returns the length of the queue
|
||||
pure fn len(&self) -> uint { self.data.len() }
|
||||
|
||||
/// Returns true if a queue contains no elements
|
||||
pure fn is_empty(&self) -> bool { self.data.is_empty() }
|
||||
}
|
||||
|
||||
impl <T: Ord> PriorityQueue<T>: Mutable {
|
||||
/// Drop all items from the queue
|
||||
fn clear(&mut self) { self.data.truncate(0) }
|
||||
}
|
||||
|
||||
impl <T: Ord> PriorityQueue<T> {
|
||||
/// Returns the greatest item in the queue - fails if empty
|
||||
pure fn top(&self) -> &self/T { &self.data[0] }
|
||||
@ -33,12 +47,6 @@ impl <T: Ord> PriorityQueue<T> {
|
||||
if self.is_empty() { None } else { Some(self.top()) }
|
||||
}
|
||||
|
||||
/// Returns the length of the queue
|
||||
pure fn len(&self) -> uint { self.data.len() }
|
||||
|
||||
/// Returns true if a queue contains no elements
|
||||
pure fn is_empty(&self) -> bool { self.data.is_empty() }
|
||||
|
||||
/// Returns true if a queue contains some elements
|
||||
pure fn is_not_empty(&self) -> bool { self.data.is_not_empty() }
|
||||
|
||||
@ -51,9 +59,6 @@ impl <T: Ord> PriorityQueue<T> {
|
||||
vec::reserve_at_least(&mut self.data, n)
|
||||
}
|
||||
|
||||
/// Drop all items from the queue
|
||||
fn clear(&mut self) { self.data.truncate(0) }
|
||||
|
||||
/// Pop the greatest item from the queue - fails if empty
|
||||
fn pop(&mut self) -> T {
|
||||
let mut item = self.data.pop();
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
|
||||
use core::container::Set;
|
||||
use core::container::{Container, Mutable, Map, Set};
|
||||
use core::cmp::{Eq, Ord};
|
||||
use core::option::{Option, Some, None};
|
||||
use core::prelude::*;
|
||||
@ -64,23 +64,30 @@ impl <K: Eq Ord, V: Eq> TreeMap<K, V>: Eq {
|
||||
true
|
||||
}
|
||||
}
|
||||
pure fn ne(&self, other: &TreeMap<K, V>) -> bool {
|
||||
!self.eq(other)
|
||||
}
|
||||
pure fn ne(&self, other: &TreeMap<K, V>) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
impl <K: Ord, V> TreeMap<K, V> {
|
||||
/// Create an empty TreeMap
|
||||
static pure fn new() -> TreeMap<K, V> { TreeMap{root: None, length: 0} }
|
||||
|
||||
impl <K: Ord, V> TreeMap<K, V>: Container {
|
||||
/// Return the number of elements in the map
|
||||
pure fn len(&self) -> uint { self.length }
|
||||
|
||||
/// Return true if the map contains no elements
|
||||
pure fn is_empty(&self) -> bool { self.root.is_none() }
|
||||
}
|
||||
|
||||
/// Return true if the map contains some elements
|
||||
pure fn is_not_empty(&self) -> bool { self.root.is_some() }
|
||||
impl <K: Ord, V> TreeMap<K, V>: Mutable {
|
||||
/// Clear the map, removing all key-value pairs.
|
||||
fn clear(&mut self) {
|
||||
self.root = None;
|
||||
self.length = 0
|
||||
}
|
||||
}
|
||||
|
||||
impl <K: Ord, V> TreeMap<K, V>: Map<K, V> {
|
||||
/// Return true if the map contains a value for the specified key
|
||||
pure fn contains_key(&self, key: &K) -> bool {
|
||||
self.find(key).is_some()
|
||||
}
|
||||
|
||||
/// Visit all key-value pairs in order
|
||||
pure fn each(&self, f: fn(&K, &V) -> bool) { each(&self.root, f) }
|
||||
@ -91,6 +98,31 @@ impl <K: Ord, V> TreeMap<K, V> {
|
||||
/// Visit all values in order
|
||||
pure fn each_value(&self, f: fn(&V) -> bool) { self.each(|_, v| f(v)) }
|
||||
|
||||
/// Insert a key-value pair into the map. An existing value for a
|
||||
/// key is replaced by the new value. Return true if the key did
|
||||
/// not already exist in the map.
|
||||
fn insert(&mut self, key: K, value: V) -> bool {
|
||||
let ret = insert(&mut self.root, key, value);
|
||||
if ret { self.length += 1 }
|
||||
ret
|
||||
}
|
||||
|
||||
/// Remove a key-value pair from the map. Return true if the key
|
||||
/// was present in the map, otherwise false.
|
||||
fn remove(&mut self, key: &K) -> bool {
|
||||
let ret = remove(&mut self.root, key);
|
||||
if ret { self.length -= 1 }
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl <K: Ord, V> TreeMap<K, V> {
|
||||
/// Create an empty TreeMap
|
||||
static pure fn new() -> TreeMap<K, V> { TreeMap{root: None, length: 0} }
|
||||
|
||||
/// Return true if the map contains some elements
|
||||
pure fn is_not_empty(&self) -> bool { self.root.is_some() }
|
||||
|
||||
/// Visit all key-value pairs in reverse order
|
||||
pure fn each_reverse(&self, f: fn(&K, &V) -> bool) {
|
||||
each_reverse(&self.root, f);
|
||||
@ -106,11 +138,6 @@ impl <K: Ord, V> TreeMap<K, V> {
|
||||
self.each_reverse(|_, v| f(v))
|
||||
}
|
||||
|
||||
/// Return true if the map contains a value for the specified key
|
||||
pure fn contains_key(&self, key: &K) -> bool {
|
||||
self.find(key).is_some()
|
||||
}
|
||||
|
||||
/// Return the value corresponding to the key in the map
|
||||
pure fn find(&self, key: &K) -> Option<&self/V> {
|
||||
let mut current: &self/Option<~TreeNode<K, V>> = &self.root;
|
||||
@ -131,23 +158,6 @@ impl <K: Ord, V> TreeMap<K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert a key-value pair into the map. An existing value for a
|
||||
/// key is replaced by the new value. Return true if the key did
|
||||
/// not already exist in the map.
|
||||
fn insert(&mut self, key: K, value: V) -> bool {
|
||||
let ret = insert(&mut self.root, key, value);
|
||||
if ret { self.length += 1 }
|
||||
ret
|
||||
}
|
||||
|
||||
/// Remove a key-value pair from the map. Return true if the key
|
||||
/// was present in the map, otherwise false.
|
||||
fn remove(&mut self, key: &K) -> bool {
|
||||
let ret = remove(&mut self.root, key);
|
||||
if ret { self.length -= 1 }
|
||||
ret
|
||||
}
|
||||
|
||||
/// Get a lazy iterator over the key-value pairs in the map.
|
||||
/// Requires that it be frozen (immutable).
|
||||
pure fn iter(&self) -> TreeMapIterator/&self<K, V> {
|
||||
@ -198,6 +208,19 @@ impl <T: Eq Ord> TreeSet<T>: Eq {
|
||||
pure fn ne(&self, other: &TreeSet<T>) -> bool { self.map != other.map }
|
||||
}
|
||||
|
||||
impl <T: Ord> TreeSet<T>: Container {
|
||||
/// Return the number of elements in the map
|
||||
pure fn len(&self) -> uint { self.map.len() }
|
||||
|
||||
/// Return true if the map contains no elements
|
||||
pure fn is_empty(&self) -> bool { self.map.is_empty() }
|
||||
}
|
||||
|
||||
impl <T: Ord> TreeSet<T>: Mutable {
|
||||
/// Clear the set, removing all values.
|
||||
fn clear(&mut self) { self.map.clear() }
|
||||
}
|
||||
|
||||
impl <T: Ord> TreeSet<T>: Set<T> {
|
||||
/// Return true if the set contains a value
|
||||
pure fn contains(&self, value: &T) -> bool {
|
||||
@ -217,12 +240,6 @@ impl <T: Ord> TreeSet<T> {
|
||||
/// Create an empty TreeSet
|
||||
static pure fn new() -> TreeSet<T> { TreeSet{map: TreeMap::new()} }
|
||||
|
||||
/// Return the number of elements in the set
|
||||
pure fn len(&self) -> uint { self.map.len() }
|
||||
|
||||
/// Return true if the set contains no elements
|
||||
pure fn is_empty(&self) -> bool { self.map.is_empty() }
|
||||
|
||||
/// Return true if the set contains some elements
|
||||
pure fn is_not_empty(&self) -> bool { self.map.is_not_empty() }
|
||||
|
||||
@ -626,6 +643,20 @@ mod test_treemap {
|
||||
assert m.find(&2).unwrap() == &11;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clear() {
|
||||
let mut m = TreeMap::new();
|
||||
m.clear();
|
||||
assert m.insert(5, 11);
|
||||
assert m.insert(12, -3);
|
||||
assert m.insert(19, 2);
|
||||
m.clear();
|
||||
assert m.find(&5).is_none();
|
||||
assert m.find(&12).is_none();
|
||||
assert m.find(&19).is_none();
|
||||
assert m.is_empty();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u8_map() {
|
||||
let mut m = TreeMap::new();
|
||||
@ -846,6 +877,20 @@ mod test_treemap {
|
||||
mod test_set {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_clear() {
|
||||
let mut s = TreeSet::new();
|
||||
s.clear();
|
||||
assert s.insert(5);
|
||||
assert s.insert(12);
|
||||
assert s.insert(19);
|
||||
s.clear();
|
||||
assert !s.contains(&5);
|
||||
assert !s.contains(&12);
|
||||
assert !s.contains(&19);
|
||||
assert s.is_empty();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_disjoint() {
|
||||
let mut xs = TreeSet::new();
|
||||
|
Loading…
Reference in New Issue
Block a user