to_true/
lib.rs

1#![no_std]
2#![doc = include_str!("../README.md")]
3
4#[doc = include_str!("../README.md")]
5pub trait ToTrue: Sized {
6    /// Run `f` when `*self == false`, then assign `*self` to `true`
7    fn to_true<F, R>(&mut self, f: F) -> Option<R>
8    where F: FnOnce() -> R;
9
10    /// Run `f` when `*self == true`, then assign `*self` to `false`
11    fn to_false<F, R>(&mut self, f: F) -> Option<R>
12    where F: FnOnce() -> R;
13}
14impl ToTrue for bool {
15    fn to_true<F, R>(&mut self, f: F) -> Option<R>
16    where F: FnOnce() -> R,
17    {
18        if *self {
19            None
20        } else {
21            *self = true;
22            Some(f())
23        }
24    }
25
26    fn to_false<F, R>(&mut self, f: F) -> Option<R>
27    where F: FnOnce() -> R,
28    {
29        if *self {
30            *self = false;
31            Some(f())
32        } else {
33            None
34        }
35    }
36}
37
38/// ```
39/// # use to_true::InTrue;
40/// let mut state = false;
41/// let mut n = 0;
42///
43/// assert_eq!(state.in_true(|| n += 1), None);
44/// assert_eq!((n, state), (0, true));
45///
46/// assert_eq!(state.in_true(|| n += 1), Some(()));
47/// assert_eq!((n, state), (1, true));
48///
49/// assert_eq!(state.in_false(|| n += 1), None);
50/// assert_eq!((n, state), (1, false));
51///
52/// assert_eq!(state.in_false(|| n += 1), Some(()));
53/// assert_eq!((n, state), (2, false));
54/// ```
55pub trait InTrue: Sized {
56    /// Run `f` when `*self == true`, then assign `*self` to `true`
57    fn in_true<F, R>(&mut self, f: F) -> Option<R>
58    where F: FnOnce() -> R;
59
60    /// Run `f` when `*self == false`, then assign `*self` to `false`
61    fn in_false<F, R>(&mut self, f: F) -> Option<R>
62    where F: FnOnce() -> R;
63}
64impl InTrue for bool {
65    fn in_true<F, R>(&mut self, f: F) -> Option<R>
66    where F: FnOnce() -> R,
67    {
68        let old = *self;
69        *self = true;
70        old.then(f)
71    }
72
73    fn in_false<F, R>(&mut self, f: F) -> Option<R>
74    where F: FnOnce() -> R,
75    {
76        let old = *self;
77        *self = false;
78        (!old).then(f)
79    }
80}
81
82/// A closure that does not run on the first call
83///
84/// # Examples
85///
86/// ```
87/// let mut n = 0;
88/// let mut f = to_true::skip(|| {n += 1; n});
89///
90/// assert_eq!(f(), None);
91/// assert_eq!(f(), Some(1));
92/// assert_eq!(f(), Some(2));
93/// ```
94pub fn skip<R>(mut f: impl FnMut() -> R) -> impl FnMut() -> Option<R> {
95    let mut state = false;
96    move || {
97        state.in_true(&mut f)
98    }
99}
100
101/// A closure that is runs only once
102///
103/// # Examples
104///
105/// ```
106/// let mut n = 0;
107/// let mut f = to_true::once(|| {n += 1; n});
108///
109/// assert_eq!(f(), Some(1));
110/// assert_eq!(f(), None);
111/// assert_eq!(f(), None);
112/// # drop(f);
113/// assert_eq!(n, 1);
114/// ```
115pub fn once<R>(f: impl FnOnce() -> R) -> impl FnMut() -> Option<R> {
116    let mut f = Some(f);
117    move || {
118        f.take().map(|f| f())
119    }
120}