Skip to content

Commit 0058269

Browse files
committed
Map entry API: add Entry::or_insert_with_result()
Takes a default function that returns a Result, and bails out on Err cases. Use case: caches where producing the value to cache can fail.
1 parent 95545e7 commit 0058269

File tree

4 files changed

+45
-0
lines changed

4 files changed

+45
-0
lines changed

src/libcollections/btree/map.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,18 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
15221522
Vacant(entry) => entry.insert(default()),
15231523
}
15241524
}
1525+
1526+
/// Like `or_insert_with`, but doesn't insert anything if the default function
1527+
/// fails with an `Err` result.
1528+
#[unstable(feature = "map_entry_insert_with_result", issue = "33126")]
1529+
pub fn or_insert_with_result<E, F>(self, default: F) -> Result<&'a mut V, E>
1530+
where F: FnOnce() -> Result<V, E>
1531+
{
1532+
match self {
1533+
Occupied(entry) => Ok(entry.into_mut()),
1534+
Vacant(entry) => Ok(entry.insert(try!(default()))),
1535+
}
1536+
}
15251537
}
15261538

15271539
impl<'a, K: Ord, V> VacantEntry<'a, K, V> {

src/libcollectionstest/btree/map.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,16 @@ fn test_entry(){
290290
}
291291
assert_eq!(map.get(&10).unwrap(), &1000);
292292
assert_eq!(map.len(), 6);
293+
294+
// or_insert_with family
295+
assert_eq!(map.entry(10).or_insert_with(|| 100), &1000);
296+
assert_eq!(map.len(), 6);
297+
assert_eq!(map.entry(20).or_insert_with(|| 200), &200);
298+
assert_eq!(map.len(), 7);
299+
assert_eq!(map.entry(30).or_insert_with_result(|| Ok::<_, &str>(300)), Ok(&mut 300));
300+
assert_eq!(map.len(), 8);
301+
assert_eq!(map.entry(31).or_insert_with_result(|| Err("nope")), Err("nope"));
302+
assert_eq!(map.len(), 8);
293303
}
294304

295305
#[test]

src/libcollectionstest/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#![feature(unboxed_closures)]
3333
#![feature(unicode)]
3434
#![feature(vec_deque_contains)]
35+
#![feature(map_entry_insert_with_result)]
3536

3637
extern crate collections;
3738
extern crate test;

src/libstd/collections/hash/map.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,6 +1533,18 @@ impl<'a, K, V> Entry<'a, K, V> {
15331533
Vacant(entry) => entry.insert(default()),
15341534
}
15351535
}
1536+
1537+
/// Like `or_insert_with`, but doesn't insert anything if the default function
1538+
/// fails with an `Err` result.
1539+
#[unstable(feature = "map_entry_insert_with_result", issue = "33126")]
1540+
pub fn or_insert_with_result<E, F>(self, default: F) -> Result<&'a mut V, E>
1541+
where F: FnOnce() -> Result<V, E>
1542+
{
1543+
match self {
1544+
Occupied(entry) => Ok(entry.into_mut()),
1545+
Vacant(entry) => Ok(entry.insert(try!(default()))),
1546+
}
1547+
}
15361548
}
15371549

15381550
impl<'a, K, V> OccupiedEntry<'a, K, V> {
@@ -2430,6 +2442,16 @@ mod test_map {
24302442
}
24312443
assert_eq!(map.get(&10).unwrap(), &1000);
24322444
assert_eq!(map.len(), 6);
2445+
2446+
// or_insert_with family
2447+
assert_eq!(map.entry(10).or_insert_with(|| 100), &1000);
2448+
assert_eq!(map.len(), 6);
2449+
assert_eq!(map.entry(20).or_insert_with(|| 200), &200);
2450+
assert_eq!(map.len(), 7);
2451+
assert_eq!(map.entry(30).or_insert_with_result(|| Ok::<_, &str>(300)), Ok(&mut 300));
2452+
assert_eq!(map.len(), 8);
2453+
assert_eq!(map.entry(31).or_insert_with_result(|| Err("nope")), Err("nope"));
2454+
assert_eq!(map.len(), 8);
24332455
}
24342456

24352457
#[test]

0 commit comments

Comments
 (0)