Skip to content

Commit

Permalink
Rollup merge of rust-lang#70850 - ssomers:btreemap_first_last, r=Amanieu
Browse files Browse the repository at this point in the history
BTreeMap first last proposal tweaks

Clean-up and following up on a request in rust-lang#62924.

Trying the reviewer of the original code rust-lang#65637...
r? @scottmcm
  • Loading branch information
Dylan-DPC authored Apr 8, 2020
2 parents 54abd4f + 8212b97 commit b9bb126
Showing 1 changed file with 76 additions and 48 deletions.
124 changes: 76 additions & 48 deletions src/liballoc/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,11 +653,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.first_key_value(), Some((&1, &"b")));
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn first_key_value<T: ?Sized>(&self) -> Option<(&K, &V)>
where
T: Ord,
K: Borrow<T>,
{
pub fn first_key_value(&self) -> Option<(&K, &V)> {
let front = self.root.as_ref()?.as_ref().first_leaf_edge();
front.right_kv().ok().map(Handle::into_kv)
}
Expand All @@ -667,36 +663,54 @@ impl<K: Ord, V> BTreeMap<K, V> {
///
/// # Examples
///
/// Contrived way to `clear` a map:
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some(entry) = map.first_entry() {
/// let (key, val) = entry.remove_entry();
/// assert!(!map.contains_key(&key));
/// if let Some(mut entry) = map.first_entry() {
/// if *entry.key() > 0 {
/// entry.insert("first");
/// }
/// }
/// assert_eq!(*map.get(&1).unwrap(), "first");
/// assert_eq!(*map.get(&2).unwrap(), "b");
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn first_entry<T: ?Sized>(&mut self) -> Option<OccupiedEntry<'_, K, V>>
where
T: Ord,
K: Borrow<T>,
{
pub fn first_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
let front = self.root.as_mut()?.as_mut().first_leaf_edge();
if let Ok(kv) = front.right_kv() {
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
} else {
None
}
let kv = front.right_kv().ok()?;
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
}

/// Removes and returns the first element in the map.
/// The key of this element is the minimum key that was in the map.
///
/// # Examples
///
/// Draining elements in ascending order, while keeping a usable map each iteration.
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some((key, _val)) = map.pop_first() {
/// assert!(map.iter().all(|(k, _v)| *k > key));
/// }
/// assert!(map.is_empty());
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn pop_first(&mut self) -> Option<(K, V)> {
self.first_entry().map(|entry| entry.remove_entry())
}

/// Returns the last key-value pair in the map.
Expand All @@ -716,11 +730,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.last_key_value(), Some((&2, &"a")));
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn last_key_value<T: ?Sized>(&self) -> Option<(&K, &V)>
where
T: Ord,
K: Borrow<T>,
{
pub fn last_key_value(&self) -> Option<(&K, &V)> {
let back = self.root.as_ref()?.as_ref().last_leaf_edge();
back.left_kv().ok().map(Handle::into_kv)
}
Expand All @@ -730,36 +740,54 @@ impl<K: Ord, V> BTreeMap<K, V> {
///
/// # Examples
///
/// Contrived way to `clear` a map:
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some(entry) = map.last_entry() {
/// let (key, val) = entry.remove_entry();
/// assert!(!map.contains_key(&key));
/// if let Some(mut entry) = map.last_entry() {
/// if *entry.key() > 0 {
/// entry.insert("last");
/// }
/// }
/// assert_eq!(*map.get(&1).unwrap(), "a");
/// assert_eq!(*map.get(&2).unwrap(), "last");
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn last_entry<T: ?Sized>(&mut self) -> Option<OccupiedEntry<'_, K, V>>
where
T: Ord,
K: Borrow<T>,
{
pub fn last_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
let back = self.root.as_mut()?.as_mut().last_leaf_edge();
if let Ok(kv) = back.left_kv() {
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
} else {
None
}
let kv = back.left_kv().ok()?;
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
}

/// Removes and returns the last element in the map.
/// The key of this element is the maximum key that was in the map.
///
/// # Examples
///
/// Draining elements in descending order, while keeping a usable map each iteration.
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some((key, _val)) = map.pop_last() {
/// assert!(map.iter().all(|(k, _v)| *k < key));
/// }
/// assert!(map.is_empty());
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn pop_last(&mut self) -> Option<(K, V)> {
self.last_entry().map(|entry| entry.remove_entry())
}

/// Returns `true` if the map contains a value for the specified key.
Expand Down

0 comments on commit b9bb126

Please sign in to comment.