Skip to content

Commit b97b605

Browse files
committed
Auto merge of #38733 - sfackler:peek-mut-pop, r=alexcrichton
Add PeekMut::pop A fairly common workflow is to put a bunch of stuff into a binary heap and then mutate the top value until its empty. This both makes that a bit more convenient (no need to save a boolean off and pop after to avoid borrowck issues), and a bit more efficient since you only shift once. r? @alexcrichton cc @rust-lang/libs
2 parents 3191886 + 54dc533 commit b97b605

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

src/libcollections/binary_heap.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,7 @@
153153

154154
use core::ops::{Deref, DerefMut};
155155
use core::iter::{FromIterator, FusedIterator};
156-
use core::mem::swap;
157-
use core::mem::size_of;
156+
use core::mem::{swap, size_of};
158157
use core::ptr;
159158
use core::fmt;
160159

@@ -226,12 +225,15 @@ pub struct BinaryHeap<T> {
226225
#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
227226
pub struct PeekMut<'a, T: 'a + Ord> {
228227
heap: &'a mut BinaryHeap<T>,
228+
sift: bool,
229229
}
230230

231231
#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
232232
impl<'a, T: Ord> Drop for PeekMut<'a, T> {
233233
fn drop(&mut self) {
234-
self.heap.sift_down(0);
234+
if self.sift {
235+
self.heap.sift_down(0);
236+
}
235237
}
236238
}
237239

@@ -250,6 +252,16 @@ impl<'a, T: Ord> DerefMut for PeekMut<'a, T> {
250252
}
251253
}
252254

255+
impl<'a, T: Ord> PeekMut<'a, T> {
256+
/// Removes the peeked value from the heap and returns it.
257+
#[unstable(feature = "binary_heap_peek_mut_pop", issue = "38863")]
258+
pub fn pop(mut this: PeekMut<'a, T>) -> T {
259+
let value = this.heap.pop().unwrap();
260+
this.sift = false;
261+
value
262+
}
263+
}
264+
253265
#[stable(feature = "rust1", since = "1.0.0")]
254266
impl<T: Clone> Clone for BinaryHeap<T> {
255267
fn clone(&self) -> Self {
@@ -385,7 +397,10 @@ impl<T: Ord> BinaryHeap<T> {
385397
if self.is_empty() {
386398
None
387399
} else {
388-
Some(PeekMut { heap: self })
400+
Some(PeekMut {
401+
heap: self,
402+
sift: true,
403+
})
389404
}
390405
}
391406

src/libcollectionstest/binary_heap.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use std::collections::BinaryHeap;
12-
use std::collections::binary_heap::Drain;
12+
use std::collections::binary_heap::{Drain, PeekMut};
1313

1414
#[test]
1515
fn test_iterator() {
@@ -94,6 +94,19 @@ fn test_peek_mut() {
9494
assert_eq!(heap.peek(), Some(&9));
9595
}
9696

97+
#[test]
98+
fn test_peek_mut_pop() {
99+
let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
100+
let mut heap = BinaryHeap::from(data);
101+
assert_eq!(heap.peek(), Some(&10));
102+
{
103+
let mut top = heap.peek_mut().unwrap();
104+
*top -= 2;
105+
assert_eq!(PeekMut::pop(top), 8);
106+
}
107+
assert_eq!(heap.peek(), Some(&9));
108+
}
109+
97110
#[test]
98111
fn test_push() {
99112
let mut heap = BinaryHeap::from(vec![2, 4, 9]);

src/libcollectionstest/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#![deny(warnings)]
1212

1313
#![feature(binary_heap_extras)]
14+
#![feature(binary_heap_peek_mut_pop)]
1415
#![feature(box_syntax)]
1516
#![feature(btree_range)]
1617
#![feature(collection_placement)]

0 commit comments

Comments
 (0)