map_self/lib.rs
1#![warn(clippy::pedantic)]
2
3/// Functions to transform a type itself instead of something it contains with the usual closure approach.
4pub trait MapSelf {
5 fn map_self<O, T>(self, op: O) -> T
6 where
7 O: FnOnce(Self) -> T,
8 Self: Sized,
9 {
10 #![must_use]
11 //! Example:
12 //!
13 //! ```ignore
14 //! let (hour, meridiem) = if use_12_hour_clock {
15 //! self.hour_meridiem() // Yields 12-hour clock time.
16 //! .map_self(|(hour, meridiem)| (hour, Some(meridiem)))
17 //! } else {
18 //! (self.hour, None)
19 //! };
20 //! ```
21
22 op(self)
23 }
24
25 fn map_self_or_keep<O>(self, op: O) -> Self
26 where
27 O: FnOnce(&Self) -> Option<Self>,
28 Self: Sized,
29 {
30 #![must_use]
31 //! Example:
32 //!
33 //! ```ignore
34 //! // Initialize time to check for double-click.
35 //! let mut last_click_time = Instant::now()
36 //! .map_self_or_keep(|now| now.checked_sub(Duration::from_secs(60)));
37 //! ```
38
39 op(&self).unwrap_or(self)
40 }
41}
42
43impl<T> MapSelf for T {}
44
45#[cfg(test)]
46mod tests {
47 use crate::MapSelf;
48
49 #[test]
50 fn map_self() {
51 assert_eq!(
52 (1, 2).map_self(|(first, second)| (first + 1, Some(second - 1))),
53 (2, Some(1))
54 );
55 assert_eq!((1, 2).map_self(|(first, second)| first + second), 3);
56 }
57
58 #[test]
59 fn map_self_or_keep() {
60 let only_positive: usize = 10;
61 assert_eq!(
62 only_positive.map_self_or_keep(|val| val.checked_sub(100)),
63 10
64 );
65 assert_eq!(only_positive.map_self_or_keep(|val| val.checked_sub(5)), 5);
66 }
67}