Skip to content

Commit

Permalink
Initial broken implementation of placement insert for BTreeMap
Browse files Browse the repository at this point in the history
  • Loading branch information
mattico committed Mar 9, 2017
1 parent 3087a1f commit 3256e95
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 1 deletion.
58 changes: 57 additions & 1 deletion src/libcollections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use core::fmt::Debug;
use core::hash::{Hash, Hasher};
use core::iter::{FromIterator, Peekable, FusedIterator};
use core::marker::PhantomData;
use core::ops::Index;
use core::ops::{Index, InPlace, Place, Placer};
use core::{fmt, intrinsics, mem, ptr};

use borrow::Borrow;
Expand Down Expand Up @@ -447,6 +447,62 @@ impl<'a, K: 'a + Debug + Ord, V: 'a + Debug> Debug for OccupiedEntry<'a, K, V> {
}
}

/// A place for insertion to a `Entry`.
///
/// See [`BTreeMap::entry`](struct.BTreeMap.html#method.entry) for details.
#[must_use = "places do nothing unless written to with <- syntax"]
#[unstable(feature = "collection_placement",
reason = "struct name and placement protocol is subject to change",
issue = "30172")]
#[derive(Debug)]
pub struct EntryPlace<'a, K: 'a + Debug + Ord, V: 'a> {
entry: Entry<'a, K, V>,
value: V,
}

#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
impl<'a, K, V> Placer<V> for Entry<'a, K, V>
where K: 'a + Debug + Ord {
type Place = EntryPlace<'a, K, V>;

fn make_place(self) -> EntryPlace<'a, K, V> {
let uninit = unsafe { mem::uninitialized() };
EntryPlace { entry: self, value: uninit }
}
}

#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
impl<'a, K, V> Place<V> for EntryPlace<'a, K, V>
where K: 'a + Debug + Ord {
fn pointer(&mut self) -> *mut V {
&mut self.value
}
}

#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
impl<'a, K, V> InPlace<V> for EntryPlace<'a, K, V>
where K: 'a + Debug + Ord {
type Owner = ();

unsafe fn finalize(self) {
match self.entry {
Occupied(mut o) => {
o.insert(self.value);
}
Vacant(v) => {
v.insert(self.value);
}
}
}
}


// An iterator for merging two sorted sequences into one
struct MergeIter<K, V, I: Iterator<Item = (K, V)>> {
left: Peekable<I>,
Expand Down
27 changes: 27 additions & 0 deletions src/libcollectionstest/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::collections::BTreeMap;
use std::collections::Bound::{self, Excluded, Included, Unbounded};
use std::collections::btree_map::Entry::{Occupied, Vacant};
use std::rc::Rc;
use panic;

use std::iter::FromIterator;
use super::DeterministicRng;
Expand Down Expand Up @@ -685,3 +686,29 @@ fn test_split_off_large_random_sorted() {
assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key)));
assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key)));
}

#[test]
fn test_placement_in() {
let mut map = HashMap::new();
map.extend((0..10).map(|i| (i, i)));

map.entry(100) <- 100;
assert_eq!(map[&100], 100);

map.entry(0) <- 10;
assert_eq!(map[&0], 10);

assert_eq!(map.len(), 11);
}

#[test]
fn test_placement_panic() {
let mut map = HashMap::new();
map.extend((0..10).map(|i| (i, i)));

fn mkpanic() -> usize { panic!() }

let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(0) <- mkpanic(); }));
assert_eq!(map.len(), 10);
assert_eq!(map[&0], 0);
}

0 comments on commit 3256e95

Please sign in to comment.