Skip to content

Commit

Permalink
libcollections: use BorrowFrom in TreeSet, Map
Browse files Browse the repository at this point in the history
This commit generalizes methods like `get` and `remove` for `TreeMap`
and `TreeSet` to use the new `std::borrow` infrastructure.

[breaking-change]
  • Loading branch information
aturon committed Nov 17, 2014
1 parent 4ab2235 commit 5eec666
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 17 deletions.
54 changes: 39 additions & 15 deletions src/libcollections/tree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use core::prelude::*;

use alloc::boxed::Box;

use core::borrow::BorrowFrom;
use core::default::Default;
use core::fmt;
use core::fmt::Show;
Expand Down Expand Up @@ -188,16 +190,16 @@ impl<K: Ord, V> Default for TreeMap<K,V> {
fn default() -> TreeMap<K, V> { TreeMap::new() }
}

impl<K: Ord, V> Index<K, V> for TreeMap<K, V> {
impl<K: Ord, Sized? Q, V> Index<Q, V> for TreeMap<K, V> where Q: BorrowFrom<K> + Ord {
#[inline]
fn index<'a>(&'a self, i: &K) -> &'a V {
fn index<'a>(&'a self, i: &Q) -> &'a V {
self.get(i).expect("no entry found for key")
}
}

impl<K: Ord, V> IndexMut<K, V> for TreeMap<K, V> {
impl<K: Ord, Sized? Q, V> IndexMut<Q, V> for TreeMap<K, V> where Q: BorrowFrom<K> + Ord {
#[inline]
fn index_mut<'a>(&'a mut self, i: &K) -> &'a mut V {
fn index_mut<'a>(&'a mut self, i: &Q) -> &'a mut V {
self.get_mut(i).expect("no entry found for key")
}
}
Expand Down Expand Up @@ -446,6 +448,9 @@ impl<K: Ord, V> TreeMap<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 @@ -458,12 +463,17 @@ impl<K: Ord, V> TreeMap<K, V> {
/// ```
#[inline]
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn get(&self, key: &K) -> Option<&V> {
tree_find_with(&self.root, |k2| key.cmp(k2))
pub fn get<Sized? Q>(&self, key: &Q) -> Option<&V>
where Q: BorrowFrom<K> + Ord
{
tree_find_with(&self.root, |k2| key.cmp(BorrowFrom::borrow_from(k2)))
}

/// 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 @@ -476,7 +486,9 @@ impl<K: Ord, V> TreeMap<K, V> {
/// ```
#[inline]
#[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 @@ -488,6 +500,9 @@ impl<K: Ord, V> TreeMap<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 @@ -503,8 +518,10 @@ impl<K: Ord, V> TreeMap<K, V> {
/// ```
#[inline]
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
tree_find_with_mut(&mut self.root, |x| key.cmp(x))
pub fn get_mut<Sized? Q>(&mut self, key: &Q) -> Option<&mut V>
where Q: BorrowFrom<K> + Ord
{
tree_find_with_mut(&mut self.root, |x| key.cmp(BorrowFrom::borrow_from(x)))
}

/// Deprecated: Renamed to `insert`.
Expand Down Expand Up @@ -545,6 +562,9 @@ impl<K: Ord, V> TreeMap<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 @@ -556,7 +576,9 @@ impl<K: Ord, V> TreeMap<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
{
let ret = remove(&mut self.root, key);
if ret.is_some() { self.length -= 1 }
ret
Expand Down Expand Up @@ -589,6 +611,7 @@ impl<K, V> TreeMap<K, V> {
/// assert_eq!((*ua.unwrap()).as_slice(), "Curl-Rust/0.1");
/// ```
#[inline]
#[experimental = "likely to be renamed, may be removed"]
pub fn find_with(&self, f:|&K| -> Ordering) -> Option<&V> {
tree_find_with(&self.root, f)
}
Expand All @@ -613,6 +636,7 @@ impl<K, V> TreeMap<K, V> {
/// assert_eq!(t.get(&"User-Agent"), Some(&new_ua));
/// ```
#[inline]
#[experimental = "likely to be renamed, may be removed"]
pub fn find_with_mut<'a>(&'a mut self, f:|&K| -> Ordering) -> Option<&'a mut V> {
tree_find_with_mut(&mut self.root, f)
}
Expand Down Expand Up @@ -1168,10 +1192,11 @@ fn insert<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>,
}
}

fn remove<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>,
key: &K) -> Option<V> {
fn remove<K, Sized? Q, V>(node: &mut Option<Box<TreeNode<K, V>>>, key: &Q) -> Option<V>
where K: Ord, Q: BorrowFrom<K> + Ord
{
fn heir_swap<K: Ord, V>(node: &mut Box<TreeNode<K, V>>,
child: &mut Option<Box<TreeNode<K, V>>>) {
child: &mut Option<Box<TreeNode<K, V>>>) {
// *could* be done without recursion, but it won't borrow check
for x in child.iter_mut() {
if x.right.is_some() {
Expand All @@ -1188,7 +1213,7 @@ fn remove<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>,
return None; // bottom of tree
}
Some(ref mut save) => {
let (ret, rebalance) = match key.cmp(&save.key) {
let (ret, rebalance) = match key.cmp(BorrowFrom::borrow_from(&save.key)) {
Less => (remove(&mut save.left, key), true),
Greater => (remove(&mut save.right, key), true),
Equal => {
Expand Down Expand Up @@ -1918,4 +1943,3 @@ mod bench {
bench_iter(b, 100000);
}
}

19 changes: 17 additions & 2 deletions src/libcollections/tree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use core::prelude::*;

use core::borrow::BorrowFrom;
use core::default::Default;
use core::fmt;
use core::fmt::Show;
Expand Down Expand Up @@ -396,6 +397,10 @@ impl<T: Ord> TreeSet<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 @@ -407,7 +412,9 @@ impl<T: Ord> TreeSet<T> {
/// ```
#[inline]
#[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: Ord + BorrowFrom<T>
{
self.map.contains_key(value)
}

Expand Down Expand Up @@ -519,6 +526,10 @@ impl<T: Ord> TreeSet<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 @@ -532,7 +543,11 @@ impl<T: Ord> TreeSet<T> {
/// ```
#[inline]
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn remove(&mut self, value: &T) -> bool { self.map.remove(value).is_some() }
pub fn remove<Sized? Q>(&mut self, value: &Q) -> bool
where Q: Ord + BorrowFrom<T>
{
self.map.remove(value).is_some()
}
}

/// A lazy forward iterator over a set.
Expand Down

0 comments on commit 5eec666

Please sign in to comment.