-
-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathoption.rs
More file actions
73 lines (63 loc) · 2.41 KB
/
Copy pathoption.rs
File metadata and controls
73 lines (63 loc) · 2.41 KB
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
71
72
73
#[cfg(doc)]
use std::path::PathBuf;
use std::{borrow::Cow, ops::Deref};
/// Extension methods for [`Option`].
pub trait OptionExt<T> {
/// Returns a reference to the value if [`Some`], otherwise evaluates `default()`.
///
/// Compared to [`Option::unwrap_or_else`], this saves having to [`Clone::clone`] the value to make the types line up.
///
/// Consider using [`Self::as_deref_or_else`] instead if the type implements [`Deref`] (such as [`String`] or [`PathBuf`]).
fn as_ref_or_else(&'_ self, default: impl FnOnce() -> T) -> Cow<'_, T>
where
T: Clone;
/// Returns a reference to `self` if [`Some`], otherwise evaluates `default()`.
///
/// Compared to [`Option::unwrap_or_else`], this saves having to [`Clone::clone`] the value to make the types line up.
///
/// Consider using [`Self::as_ref_or_else`] instead if the type does not implement [`Deref`].
fn as_deref_or_else(&'_ self, default: impl FnOnce() -> T) -> Cow<'_, T::Target>
where
T: Deref,
T::Target: ToOwned<Owned = T>;
}
impl<T> OptionExt<T> for Option<T> {
fn as_ref_or_else(&'_ self, default: impl FnOnce() -> T) -> Cow<'_, T>
where
T: Clone,
{
self.as_ref()
.map_or_else(|| Cow::Owned(default()), Cow::Borrowed)
}
fn as_deref_or_else(&'_ self, default: impl FnOnce() -> T) -> Cow<'_, <T>::Target>
where
T: Deref,
<T>::Target: ToOwned<Owned = T>,
{
self.as_deref()
.map_or_else(|| Cow::Owned(default()), Cow::Borrowed)
}
}
#[cfg(test)]
mod tests {
use std::borrow::Cow;
use super::*;
#[test]
fn as_ref_or_else() {
let maybe: Option<&str> = None;
let defaulted: Cow<&str> = maybe.as_ref_or_else(|| "foo");
assert_eq!(defaulted, Cow::<&str>::Owned("foo"));
let maybe: Option<&str> = Some("foo");
let defaulted: Cow<&str> = maybe.as_ref_or_else(|| panic!());
assert_eq!(defaulted, Cow::<&str>::Borrowed(&"foo"));
}
#[test]
fn as_deref_or_else() {
let maybe: Option<String> = None;
let defaulted: Cow<str> = maybe.as_deref_or_else(|| "foo".to_string());
assert_eq!(defaulted, Cow::<str>::Owned("foo".to_string()));
let maybe: Option<String> = Some("foo".to_string());
let defaulted: Cow<str> = maybe.as_deref_or_else(|| panic!());
assert_eq!(defaulted, Cow::<str>::Borrowed("foo"));
}
}