From ff88510535611f8497047584b18b819b7fe5cb3a Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Thu, 13 Nov 2014 15:51:08 -0800 Subject: [PATCH] libcollections: generalize BTree* to use BorrowFrom Generalizes the BTree-based collections to use the new BorrowFrom infrastructure for more flexible lookups and removals. --- src/libcollections/btree/map.rs | 33 ++++++++++++++++++++++++-------- src/libcollections/btree/node.rs | 11 ++++++----- src/libcollections/btree/set.rs | 13 +++++++++++-- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 0b6d9e356b91..007e01ef9820 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -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}; @@ -184,6 +185,9 @@ impl BTreeMap { /// 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 /// /// ``` @@ -195,7 +199,7 @@ impl BTreeMap { /// 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(&self, key: &Q) -> Option<&V> where Q: BorrowFrom + Ord { let mut cur_node = &self.root; loop { match cur_node.search(key) { @@ -213,6 +217,9 @@ impl BTreeMap { /// 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 /// /// ``` @@ -224,7 +231,7 @@ impl BTreeMap { /// 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(&self, key: &Q) -> bool where Q: BorrowFrom + Ord { self.get(key).is_some() } @@ -236,6 +243,9 @@ impl BTreeMap { /// 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 /// /// ``` @@ -251,7 +261,7 @@ impl BTreeMap { /// ``` // 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(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom + Ord { // temp_node is a Borrowck hack for having a mutable value outlive a loop iteration let mut temp_node = &mut self.root; loop { @@ -410,6 +420,9 @@ impl BTreeMap { /// 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 /// /// ``` @@ -421,7 +434,7 @@ impl BTreeMap { /// assert_eq!(map.remove(&1), None); /// ``` #[unstable = "matches collection reform specification, waiting for dust to settle"] - pub fn remove(&mut self, key: &K) -> Option { + pub fn remove(&mut self, key: &Q) -> Option where Q: BorrowFrom + Ord { // See `swap` for a more thorough description of the stuff going on in here let mut stack = stack::PartialSearchStack::new(self); loop { @@ -790,14 +803,18 @@ impl Show for BTreeMap { } } -impl Index for BTreeMap { - fn index(&self, key: &K) -> &V { +impl Index for BTreeMap + where Q: BorrowFrom + Ord +{ + fn index(&self, key: &Q) -> &V { self.get(key).expect("no entry found for key") } } -impl IndexMut for BTreeMap { - fn index_mut(&mut self, key: &K) -> &mut V { +impl IndexMut for BTreeMap + where Q: BorrowFrom + Ord +{ + fn index_mut(&mut self, key: &Q) -> &mut V { self.get_mut(key).expect("no entry found for key") } } diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index 6e9341231ad6..bdd7aa9c6117 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -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; @@ -73,19 +74,19 @@ impl Node { /// 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(&self, key: &Q) -> SearchResult where Q: BorrowFrom + 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(&self, key: &Q) -> SearchResult where Q: BorrowFrom + 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()) diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 56edf7719bb2..64ae4f6a5086 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -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; @@ -167,6 +168,10 @@ impl BTreeSet { /// 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 /// /// ``` @@ -177,7 +182,7 @@ impl BTreeSet { /// 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(&self, value: &Q) -> bool where Q: BorrowFrom + Ord { self.map.contains_key(value) } @@ -291,6 +296,10 @@ impl BTreeSet { /// 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 /// /// ``` @@ -303,7 +312,7 @@ impl BTreeSet { /// 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(&mut self, value: &Q) -> bool where Q: BorrowFrom + Ord { self.map.remove(value).is_some() } }