Skip to content

Commit

Permalink
libcollections: generalize BTree* to use BorrowFrom
Browse files Browse the repository at this point in the history
Generalizes the BTree-based collections to use the new BorrowFrom
infrastructure for more flexible lookups and removals.
  • Loading branch information
aturon committed Nov 17, 2014
1 parent 7213de1 commit ff88510
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 15 deletions.
33 changes: 25 additions & 8 deletions src/libcollections/btree/map.rs
Expand Up @@ -21,6 +21,7 @@ use core::prelude::*;

use self::StackOp::*;
use super::node::*;
use core::borrow::BorrowFrom;
use std::hash::{Writer, Hash};
use core::default::Default;
use core::{iter, fmt, mem};
Expand Down Expand Up @@ -184,6 +185,9 @@ impl<K: Ord, V> BTreeMap<K, V> {

/// Returns a reference to the value corresponding to the key.
///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
///
/// # Example
///
/// ```
Expand All @@ -195,7 +199,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.get(&2), None);
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn get(&self, key: &K) -> Option<&V> {
pub fn get<Sized? Q>(&self, key: &Q) -> Option<&V> where Q: BorrowFrom<K> + Ord {
let mut cur_node = &self.root;
loop {
match cur_node.search(key) {
Expand All @@ -213,6 +217,9 @@ impl<K: Ord, V> BTreeMap<K, V> {

/// Returns true if the map contains a value for the specified key.
///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
///
/// # Example
///
/// ```
Expand All @@ -224,7 +231,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.contains_key(&2), false);
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn contains_key(&self, key: &K) -> bool {
pub fn contains_key<Sized? Q>(&self, key: &Q) -> bool where Q: BorrowFrom<K> + Ord {
self.get(key).is_some()
}

Expand All @@ -236,6 +243,9 @@ impl<K: Ord, V> BTreeMap<K, V> {

/// Returns a mutable reference to the value corresponding to the key.
///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
///
/// # Example
///
/// ```
Expand All @@ -251,7 +261,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// ```
// See `get` for implementation notes, this is basically a copy-paste with mut's added
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
pub fn get_mut<Sized? Q>(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom<K> + Ord {
// temp_node is a Borrowck hack for having a mutable value outlive a loop iteration
let mut temp_node = &mut self.root;
loop {
Expand Down Expand Up @@ -410,6 +420,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// Removes a key from the map, returning the value at the key if the key
/// was previously in the map.
///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
///
/// # Example
///
/// ```
Expand All @@ -421,7 +434,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.remove(&1), None);
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn remove(&mut self, key: &K) -> Option<V> {
pub fn remove<Sized? Q>(&mut self, key: &Q) -> Option<V> where Q: BorrowFrom<K> + Ord {
// See `swap` for a more thorough description of the stuff going on in here
let mut stack = stack::PartialSearchStack::new(self);
loop {
Expand Down Expand Up @@ -790,14 +803,18 @@ impl<K: Show, V: Show> Show for BTreeMap<K, V> {
}
}

impl<K: Ord, V> Index<K, V> for BTreeMap<K, V> {
fn index(&self, key: &K) -> &V {
impl<K: Ord, Sized? Q, V> Index<Q, V> for BTreeMap<K, V>
where Q: BorrowFrom<K> + Ord
{
fn index(&self, key: &Q) -> &V {
self.get(key).expect("no entry found for key")
}
}

impl<K: Ord, V> IndexMut<K, V> for BTreeMap<K, V> {
fn index_mut(&mut self, key: &K) -> &mut V {
impl<K: Ord, Sized? Q, V> IndexMut<Q, V> for BTreeMap<K, V>
where Q: BorrowFrom<K> + Ord
{
fn index_mut(&mut self, key: &Q) -> &mut V {
self.get_mut(key).expect("no entry found for key")
}
}
Expand Down
11 changes: 6 additions & 5 deletions src/libcollections/btree/node.rs
Expand Up @@ -19,6 +19,7 @@ use core::prelude::*;

use core::{slice, mem, ptr};
use core::iter::Zip;
use core::borrow::BorrowFrom;

use vec;
use vec::Vec;
Expand Down Expand Up @@ -73,19 +74,19 @@ impl<K: Ord, V> Node<K, V> {
/// Searches for the given key in the node. If it finds an exact match,
/// `Found` will be yielded with the matching index. If it doesn't find an exact match,
/// `GoDown` will be yielded with the index of the subtree the key must lie in.
pub fn search(&self, key: &K) -> SearchResult {
pub fn search<Sized? Q>(&self, key: &Q) -> SearchResult where Q: BorrowFrom<K> + Ord {
// FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V).
// For the B configured as of this writing (B = 6), binary search was *significantly*
// worse for uints.
self.search_linear(key)
}

fn search_linear(&self, key: &K) -> SearchResult {
fn search_linear<Sized? Q>(&self, key: &Q) -> SearchResult where Q: BorrowFrom<K> + Ord {
for (i, k) in self.keys.iter().enumerate() {
match k.cmp(key) {
Less => {},
match key.cmp(BorrowFrom::borrow_from(k)) {
Greater => {},
Equal => return Found(i),
Greater => return GoDown(i),
Less => return GoDown(i),
}
}
GoDown(self.len())
Expand Down
13 changes: 11 additions & 2 deletions src/libcollections/btree/set.rs
Expand Up @@ -15,6 +15,7 @@ use core::prelude::*;

use btree_map::{BTreeMap, Keys, MoveEntries};
use std::hash::Hash;
use core::borrow::BorrowFrom;
use core::default::Default;
use core::{iter, fmt};
use core::iter::Peekable;
Expand Down Expand Up @@ -167,6 +168,10 @@ impl<T: Ord> BTreeSet<T> {

/// Returns `true` if the set contains a value.
///
/// The value may be any borrowed form of the set's value type,
/// but the ordering on the borrowed form *must* match the
/// ordering on the value type.
///
/// # Example
///
/// ```
Expand All @@ -177,7 +182,7 @@ impl<T: Ord> BTreeSet<T> {
/// assert_eq!(set.contains(&4), false);
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn contains(&self, value: &T) -> bool {
pub fn contains<Sized? Q>(&self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
self.map.contains_key(value)
}

Expand Down Expand Up @@ -291,6 +296,10 @@ impl<T: Ord> BTreeSet<T> {
/// Removes a value from the set. Returns `true` if the value was
/// present in the set.
///
/// The value may be any borrowed form of the set's value type,
/// but the ordering on the borrowed form *must* match the
/// ordering on the value type.
///
/// # Example
///
/// ```
Expand All @@ -303,7 +312,7 @@ impl<T: Ord> BTreeSet<T> {
/// assert_eq!(set.remove(&2), false);
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn remove(&mut self, value: &T) -> bool {
pub fn remove<Sized? Q>(&mut self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
self.map.remove(value).is_some()
}
}
Expand Down

0 comments on commit ff88510

Please sign in to comment.