Skip to content

Commit 88449a8

Browse files
committed
add naivest entry API to VecMap
1 parent eaf4c5c commit 88449a8

File tree

1 file changed

+193
-1
lines changed

1 file changed

+193
-1
lines changed

src/libcollections/vec_map.rs

Lines changed: 193 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
1414
#![allow(missing_docs)]
1515

16+
pub use self::Entry::*;
17+
1618
use core::prelude::*;
1719

1820
use core::cmp::Ordering;
@@ -66,6 +68,32 @@ pub struct VecMap<V> {
6668
v: Vec<Option<V>>,
6769
}
6870

71+
/// A view into a single entry in a map, which may either be vacant or occupied.
72+
#[unstable(feature = "collections",
73+
reason = "precise API still under development")]
74+
pub enum Entry<'a, V:'a> {
75+
/// A vacant Entry
76+
Vacant(VacantEntry<'a, V>),
77+
/// An occupied Entry
78+
Occupied(OccupiedEntry<'a, V>),
79+
}
80+
81+
/// A vacant Entry.
82+
#[unstable(feature = "collections",
83+
reason = "precise API still under development")]
84+
pub struct VacantEntry<'a, V:'a> {
85+
map: &'a mut VecMap<V>,
86+
index: usize,
87+
}
88+
89+
/// An occupied Entry.
90+
#[unstable(feature = "collections",
91+
reason = "precise API still under development")]
92+
pub struct OccupiedEntry<'a, V:'a> {
93+
map: &'a mut VecMap<V>,
94+
index: usize,
95+
}
96+
6997
#[stable(feature = "rust1", since = "1.0.0")]
7098
impl<V> Default for VecMap<V> {
7199
#[stable(feature = "rust1", since = "1.0.0")]
@@ -485,6 +513,119 @@ impl<V> VecMap<V> {
485513
let result = &mut self.v[*key];
486514
result.take()
487515
}
516+
517+
/// Gets the given key's corresponding entry in the map for in-place manipulation.
518+
///
519+
/// # Examples
520+
///
521+
/// ```
522+
/// use std::collections::VecMap;
523+
/// use std::collections::vec_map::Entry;
524+
///
525+
/// let mut count: VecMap<u32> = VecMap::new();
526+
///
527+
/// // count the number of occurrences of numbers in the vec
528+
/// for x in vec![1, 2, 1, 2, 3, 4, 1, 2, 4].iter() {
529+
/// match count.entry(*x) {
530+
/// Entry::Vacant(view) => {
531+
/// view.insert(1);
532+
/// },
533+
/// Entry::Occupied(mut view) => {
534+
/// let v = view.get_mut();
535+
/// *v += 1;
536+
/// },
537+
/// }
538+
/// }
539+
///
540+
/// assert_eq!(count[1], 3);
541+
/// ```
542+
#[unstable(feature = "collections",
543+
reason = "precise API still under development")]
544+
pub fn entry(&mut self, key: usize) -> Entry<V> {
545+
// FIXME(Gankro): this is basically the dumbest implementation of
546+
// entry possible, because weird non-lexical borrows issues make it
547+
// completely insane to do any other way. That said, Entry is a border-line
548+
// useless construct on VecMap, so it's hardly a big loss.
549+
if self.contains_key(&key) {
550+
Occupied(OccupiedEntry {
551+
map: self,
552+
index: key,
553+
})
554+
} else {
555+
Vacant(VacantEntry {
556+
map: self,
557+
index: key,
558+
})
559+
}
560+
}
561+
}
562+
563+
564+
impl<'a, V> Entry<'a, V> {
565+
#[unstable(feature = "collections",
566+
reason = "matches collection reform v2 specification, waiting for dust to settle")]
567+
/// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
568+
pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, V>> {
569+
match self {
570+
Occupied(entry) => Ok(entry.into_mut()),
571+
Vacant(entry) => Err(entry),
572+
}
573+
}
574+
}
575+
576+
impl<'a, V> VacantEntry<'a, V> {
577+
/// Sets the value of the entry with the VacantEntry's key,
578+
/// and returns a mutable reference to it.
579+
#[unstable(feature = "collections",
580+
reason = "matches collection reform v2 specification, waiting for dust to settle")]
581+
pub fn insert(self, value: V) -> &'a mut V {
582+
let index = self.index;
583+
self.map.insert(index, value);
584+
&mut self.map[index]
585+
}
586+
}
587+
588+
impl<'a, V> OccupiedEntry<'a, V> {
589+
/// Gets a reference to the value in the entry.
590+
#[unstable(feature = "collections",
591+
reason = "matches collection reform v2 specification, waiting for dust to settle")]
592+
pub fn get(&self) -> &V {
593+
let index = self.index;
594+
&self.map[index]
595+
}
596+
597+
/// Gets a mutable reference to the value in the entry.
598+
#[unstable(feature = "collections",
599+
reason = "matches collection reform v2 specification, waiting for dust to settle")]
600+
pub fn get_mut(&mut self) -> &mut V {
601+
let index = self.index;
602+
&mut self.map[index]
603+
}
604+
605+
/// Converts the entry into a mutable reference to its value.
606+
#[unstable(feature = "collections",
607+
reason = "matches collection reform v2 specification, waiting for dust to settle")]
608+
pub fn into_mut(self) -> &'a mut V {
609+
let index = self.index;
610+
&mut self.map[index]
611+
}
612+
613+
/// Sets the value of the entry with the OccupiedEntry's key,
614+
/// and returns the entry's old value.
615+
#[unstable(feature = "collections",
616+
reason = "matches collection reform v2 specification, waiting for dust to settle")]
617+
pub fn insert(&mut self, value: V) -> V {
618+
let index = self.index;
619+
self.map.insert(index, value).unwrap()
620+
}
621+
622+
/// Takes the value of the entry out of the map, and returns it.
623+
#[unstable(feature = "collections",
624+
reason = "matches collection reform v2 specification, waiting for dust to settle")]
625+
pub fn remove(self) -> V {
626+
let index = self.index;
627+
self.map.remove(&index).unwrap()
628+
}
488629
}
489630

490631
#[stable(feature = "rust1", since = "1.0.0")]
@@ -787,7 +928,7 @@ mod test_map {
787928
use prelude::*;
788929
use core::hash::{hash, SipHasher};
789930

790-
use super::VecMap;
931+
use super::{VecMap, Occupied, Vacant};
791932

792933
#[test]
793934
fn test_get_mut() {
@@ -1139,6 +1280,57 @@ mod test_map {
11391280

11401281
map[4];
11411282
}
1283+
1284+
#[test]
1285+
fn test_entry(){
1286+
let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
1287+
1288+
let mut map: VecMap<i32> = xs.iter().map(|&x| x).collect();
1289+
1290+
// Existing key (insert)
1291+
match map.entry(1) {
1292+
Vacant(_) => unreachable!(),
1293+
Occupied(mut view) => {
1294+
assert_eq!(view.get(), &10);
1295+
assert_eq!(view.insert(100), 10);
1296+
}
1297+
}
1298+
assert_eq!(map.get(&1).unwrap(), &100);
1299+
assert_eq!(map.len(), 6);
1300+
1301+
1302+
// Existing key (update)
1303+
match map.entry(2) {
1304+
Vacant(_) => unreachable!(),
1305+
Occupied(mut view) => {
1306+
let v = view.get_mut();
1307+
*v *= 10;
1308+
}
1309+
}
1310+
assert_eq!(map.get(&2).unwrap(), &200);
1311+
assert_eq!(map.len(), 6);
1312+
1313+
// Existing key (take)
1314+
match map.entry(3) {
1315+
Vacant(_) => unreachable!(),
1316+
Occupied(view) => {
1317+
assert_eq!(view.remove(), 30);
1318+
}
1319+
}
1320+
assert_eq!(map.get(&3), None);
1321+
assert_eq!(map.len(), 5);
1322+
1323+
1324+
// Inexistent key (insert)
1325+
match map.entry(10) {
1326+
Occupied(_) => unreachable!(),
1327+
Vacant(view) => {
1328+
assert_eq!(*view.insert(1000), 1000);
1329+
}
1330+
}
1331+
assert_eq!(map.get(&10).unwrap(), &1000);
1332+
assert_eq!(map.len(), 6);
1333+
}
11421334
}
11431335

11441336
#[cfg(test)]

0 commit comments

Comments
 (0)