1
Fork 0

Add initial impl of placement-in for BinaryHeap

This commit is contained in:
Martin Hafskjold Thoresen 2017-01-14 13:58:41 +01:00
parent 7d82d95af9
commit fb3483c827
No known key found for this signature in database
GPG key ID: 6E3931EA32EF1E30
2 changed files with 97 additions and 1 deletions

View file

@ -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;
@ -688,6 +688,22 @@ impl<T: Ord> BinaryHeap<T> {
}
}
fn sift_up_ind(&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);
while hole.pos() > start {
let parent = (hole.pos() - 1) / 2;
if hole.element() <= hole.get(parent) {
return hole.pos();
}
hole.move_to(parent);
}
hole.pos()
}
}
/// Take an element at `pos` and move it down the heap,
/// while its children are larger.
fn sift_down_range(&mut self, pos: usize, end: usize) {
@ -889,6 +905,19 @@ impl<T: Ord> BinaryHeap<T> {
}
}
impl<T> BinaryHeap<T>
where T: Clone + Ord {
/// kek
#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
pub fn place(&mut self) -> PlaceIn<T> {
PlaceIn {
heap: self,
}
}
}
/// Hole represents a hole in a slice i.e. an index without valid value
/// (because it was moved from or duplicated).
/// In drop, `Hole` will restore the slice by filling the hole
@ -1189,3 +1218,49 @@ 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 PlaceIn<'a, T: 'a>
where T: Clone + Ord {
heap: &'a mut BinaryHeap<T>,
}
#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
impl<'a, T> Place<T> for PlaceIn<'a, T>
where T: Clone + Ord {
fn pointer(&mut self) -> *mut T {
self.heap.data.place_back().pointer()
}
}
#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
impl<'a, T> Placer<T> for PlaceIn<'a, T>
where T: Clone + Ord {
type Place = PlaceIn<'a, T>;
fn make_place(self) -> Self {
let _ = self.heap.data.place_back().make_place();
self
}
}
#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
impl<'a, T> InPlace<T> for PlaceIn<'a, T>
where T: Clone + Ord {
type Owner = &'a T;
unsafe fn finalize(self) -> &'a T {
let len = self.heap.len();
let _ = self.heap.data.place_back().finalize();
let i = self.heap.sift_up_ind(0, len);
&mut self.heap.data[i]
}
}

View file

@ -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();
a.place() <- 2;
a.place() <- 4;
a.place() <- 3;
assert_eq!(a.peek(), Some(&4));
assert_eq!(a.len(), 3);
a.place() <- 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(|| { heap.place() <- mkpanic(); }));
assert_eq!(heap.len(), 3);
}
#[allow(dead_code)]
fn assert_covariance() {
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {