1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
pub trait OptionInsertExt<T> {
fn get_or_try_insert_with<F, E>(&mut self, f: F) -> Result<&mut T, E>
where
F: FnOnce() -> Result<T, E>;
}
impl<T> OptionInsertExt<T> for Option<T> {
#[inline]
fn get_or_try_insert_with<F, E>(&mut self, f: F) -> Result<&mut T, E>
where
F: FnOnce() -> Result<T, E>,
{
if let None = *self {
*self = Some(f()?);
}
match self {
Some(v) => Ok(v),
None => unsafe { core::hint::unreachable_unchecked() },
}
}
}
#[cfg(test)]
mod tests {
use super::OptionInsertExt;
#[test]
fn it_works_when_some() {
let mut opt = Some(0);
*opt.get_or_try_insert_with::<_, ()>(|| Ok(3)).unwrap() += 1;
*opt.get_or_try_insert_with::<_, ()>(|| Err(())).unwrap() += 1;
assert_eq!(opt, Some(2));
}
#[test]
fn it_works_when_none() {
let mut opt = None;
opt.get_or_try_insert_with::<_, ()>(|| Ok(1)).unwrap();
assert_eq!(opt, Some(1));
}
#[test]
fn it_errors() {
let mut opt: Option<i32> = None;
assert_eq!(opt.get_or_try_insert_with(|| Err(())), Err(()));
}
}