Skip to content

Commit 3256e95

Browse files
committed
Initial broken implementation of placement insert for BTreeMap
See: rust-lang#40390
1 parent 3087a1f commit 3256e95

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

src/libcollections/btree/map.rs

+57-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use core::fmt::Debug;
1313
use core::hash::{Hash, Hasher};
1414
use core::iter::{FromIterator, Peekable, FusedIterator};
1515
use core::marker::PhantomData;
16-
use core::ops::Index;
16+
use core::ops::{Index, InPlace, Place, Placer};
1717
use core::{fmt, intrinsics, mem, ptr};
1818

1919
use borrow::Borrow;
@@ -447,6 +447,62 @@ impl<'a, K: 'a + Debug + Ord, V: 'a + Debug> Debug for OccupiedEntry<'a, K, V> {
447447
}
448448
}
449449

450+
/// A place for insertion to a `Entry`.
451+
///
452+
/// See [`BTreeMap::entry`](struct.BTreeMap.html#method.entry) for details.
453+
#[must_use = "places do nothing unless written to with <- syntax"]
454+
#[unstable(feature = "collection_placement",
455+
reason = "struct name and placement protocol is subject to change",
456+
issue = "30172")]
457+
#[derive(Debug)]
458+
pub struct EntryPlace<'a, K: 'a + Debug + Ord, V: 'a> {
459+
entry: Entry<'a, K, V>,
460+
value: V,
461+
}
462+
463+
#[unstable(feature = "collection_placement",
464+
reason = "placement protocol is subject to change",
465+
issue = "30172")]
466+
impl<'a, K, V> Placer<V> for Entry<'a, K, V>
467+
where K: 'a + Debug + Ord {
468+
type Place = EntryPlace<'a, K, V>;
469+
470+
fn make_place(self) -> EntryPlace<'a, K, V> {
471+
let uninit = unsafe { mem::uninitialized() };
472+
EntryPlace { entry: self, value: uninit }
473+
}
474+
}
475+
476+
#[unstable(feature = "collection_placement",
477+
reason = "placement protocol is subject to change",
478+
issue = "30172")]
479+
impl<'a, K, V> Place<V> for EntryPlace<'a, K, V>
480+
where K: 'a + Debug + Ord {
481+
fn pointer(&mut self) -> *mut V {
482+
&mut self.value
483+
}
484+
}
485+
486+
#[unstable(feature = "collection_placement",
487+
reason = "placement protocol is subject to change",
488+
issue = "30172")]
489+
impl<'a, K, V> InPlace<V> for EntryPlace<'a, K, V>
490+
where K: 'a + Debug + Ord {
491+
type Owner = ();
492+
493+
unsafe fn finalize(self) {
494+
match self.entry {
495+
Occupied(mut o) => {
496+
o.insert(self.value);
497+
}
498+
Vacant(v) => {
499+
v.insert(self.value);
500+
}
501+
}
502+
}
503+
}
504+
505+
450506
// An iterator for merging two sorted sequences into one
451507
struct MergeIter<K, V, I: Iterator<Item = (K, V)>> {
452508
left: Peekable<I>,

src/libcollectionstest/btree/map.rs

+27
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::collections::BTreeMap;
1212
use std::collections::Bound::{self, Excluded, Included, Unbounded};
1313
use std::collections::btree_map::Entry::{Occupied, Vacant};
1414
use std::rc::Rc;
15+
use panic;
1516

1617
use std::iter::FromIterator;
1718
use super::DeterministicRng;
@@ -685,3 +686,29 @@ fn test_split_off_large_random_sorted() {
685686
assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key)));
686687
assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key)));
687688
}
689+
690+
#[test]
691+
fn test_placement_in() {
692+
let mut map = HashMap::new();
693+
map.extend((0..10).map(|i| (i, i)));
694+
695+
map.entry(100) <- 100;
696+
assert_eq!(map[&100], 100);
697+
698+
map.entry(0) <- 10;
699+
assert_eq!(map[&0], 10);
700+
701+
assert_eq!(map.len(), 11);
702+
}
703+
704+
#[test]
705+
fn test_placement_panic() {
706+
let mut map = HashMap::new();
707+
map.extend((0..10).map(|i| (i, i)));
708+
709+
fn mkpanic() -> usize { panic!() }
710+
711+
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(0) <- mkpanic(); }));
712+
assert_eq!(map.len(), 10);
713+
assert_eq!(map[&0], 0);
714+
}

0 commit comments

Comments
 (0)