diff options
| author | bors <bors@rust-lang.org> | 2017-01-20 13:31:10 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-01-20 13:31:10 +0000 |
| commit | a52da95ced667fe8ff490f73c0b041a4f926c041 (patch) | |
| tree | 47ddc462587966f85127bc05492fcaff9fc07a49 | |
| parent | b7ca2b9e143248c8fc33353636c0051f91d7f77f (diff) | |
| parent | 90fbe155f2104c9cbbec5ff1e79ee513e112fa9c (diff) | |
| download | rust-a52da95ced667fe8ff490f73c0b041a4f926c041.tar.gz rust-a52da95ced667fe8ff490f73c0b041a4f926c041.zip | |
Auto merge of #39062 - martinhath:placement-in-binaryheap, r=nagisa
Implement placement-in protocol for `BinaryHeap` Related to #30172, and loosley based on #38551. At the moment, this PR is in a pretty rough state, but I wanted to get some feedback to see if I'm going in the right direction. I hope the Mentor label of #30172 is still applicable, even though it's a year old 😄
| -rw-r--r-- | src/libcollections/binary_heap.rs | 58 | ||||
| -rw-r--r-- | src/libcollectionstest/binary_heap.rs | 21 |
2 files changed, 77 insertions, 2 deletions
diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 7d245f79f69..b7c2a708baf 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -151,7 +151,7 @@ #![allow(missing_docs)] #![stable(feature = "rust1", since = "1.0.0")] -use core::ops::{Deref, DerefMut}; +use core::ops::{Deref, DerefMut, Place, Placer, InPlace}; use core::iter::{FromIterator, FusedIterator}; use core::mem::{swap, size_of}; use core::ptr; @@ -673,7 +673,7 @@ impl<T: Ord> BinaryHeap<T> { // the hole is filled back at the end of its scope, even on panic. // Using a hole reduces the constant factor compared to using swaps, // which involves twice as many moves. - fn sift_up(&mut self, start: usize, pos: usize) { + fn sift_up(&mut self, start: usize, pos: usize) -> usize { unsafe { // Take out the value at `pos` and create a hole. let mut hole = Hole::new(&mut self.data, pos); @@ -685,6 +685,7 @@ impl<T: Ord> BinaryHeap<T> { } hole.move_to(parent); } + hole.pos() } } @@ -1189,3 +1190,56 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> { self.extend(iter.into_iter().cloned()); } } + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +pub struct BinaryHeapPlace<'a, T: 'a> +where T: Clone + Ord { + heap: *mut BinaryHeap<T>, + place: vec::PlaceBack<'a, T>, +} + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +impl<'a, T: 'a> Placer<T> for &'a mut BinaryHeap<T> +where T: Clone + Ord { + type Place = BinaryHeapPlace<'a, T>; + + fn make_place(self) -> Self::Place { + let ptr = self as *mut BinaryHeap<T>; + let place = Placer::make_place(self.data.place_back()); + BinaryHeapPlace { + heap: ptr, + place: place, + } + } +} + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +impl<'a, T> Place<T> for BinaryHeapPlace<'a, T> +where T: Clone + Ord { + fn pointer(&mut self) -> *mut T { + self.place.pointer() + } +} + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +impl<'a, T> InPlace<T> for BinaryHeapPlace<'a, T> +where T: Clone + Ord { + type Owner = &'a T; + + unsafe fn finalize(self) -> &'a T { + self.place.finalize(); + + let heap: &mut BinaryHeap<T> = &mut *self.heap; + let len = heap.len(); + let i = heap.sift_up(0, len - 1); + heap.data.get_unchecked(i) + } +} diff --git a/src/libcollectionstest/binary_heap.rs b/src/libcollectionstest/binary_heap.rs index 1df341d1fc2..d284937a9e6 100644 --- a/src/libcollectionstest/binary_heap.rs +++ b/src/libcollectionstest/binary_heap.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::panic; use std::collections::BinaryHeap; use std::collections::binary_heap::{Drain, PeekMut}; @@ -310,6 +311,26 @@ fn test_extend_specialization() { assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); } +#[test] +fn test_placement() { + let mut a = BinaryHeap::new(); + &mut a <- 2; + &mut a <- 4; + &mut a <- 3; + assert_eq!(a.peek(), Some(&4)); + assert_eq!(a.len(), 3); + &mut a <- 1; + assert_eq!(a.into_sorted_vec(), vec![1, 2, 3, 4]); +} + +#[test] +fn test_placement_panic() { + let mut heap = BinaryHeap::from(vec![1, 2, 3]); + fn mkpanic() -> usize { panic!() } + let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { &mut heap <- mkpanic(); })); + assert_eq!(heap.len(), 3); +} + #[allow(dead_code)] fn assert_covariance() { fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { |
