Skip to main content

tuwunel_core/utils/
bool.rs

1//! Trait BoolExt
2
3use futures::future::OptionFuture;
4
5/// Boolean extensions and chain.starters
6pub trait BoolExt {
7	fn and<T>(self, t: Option<T>) -> Option<T>;
8
9	#[must_use]
10	fn and_is(self, b: bool) -> bool;
11
12	#[must_use]
13	fn and_if<F: FnOnce() -> bool>(self, f: F) -> bool;
14
15	fn and_then<T, F: FnOnce() -> Option<T>>(self, f: F) -> Option<T>;
16
17	#[must_use]
18	fn clone_or<T: Clone>(self, err: T, t: &T) -> T;
19
20	#[must_use]
21	fn copy_or<T: Copy>(self, err: T, t: T) -> T;
22
23	#[must_use]
24	fn expect(self, msg: &str) -> Self;
25
26	#[must_use]
27	fn expect_false(self, msg: &str) -> Self;
28
29	fn into_option(self) -> Option<()>;
30
31	#[expect(clippy::result_unit_err)]
32	fn into_result(self) -> Result<(), ()>;
33
34	#[must_use]
35	fn is_false(&self) -> Self;
36
37	fn map<T, F: FnOnce(Self) -> T>(self, f: F) -> T
38	where
39		Self: Sized;
40
41	fn map_ok_or<T, E, F: FnOnce() -> T>(self, err: E, f: F) -> Result<T, E>;
42
43	fn map_or<T, F: FnOnce() -> T>(self, err: T, f: F) -> T;
44
45	fn map_or_else<T, E: FnOnce() -> T, F: FnOnce() -> T>(self, err: E, f: F) -> T;
46
47	fn ok_or<E>(self, err: E) -> Result<(), E>;
48
49	fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<(), E>;
50
51	fn or<T, F: FnOnce() -> T>(self, f: F) -> Option<T>;
52
53	fn or_some<T>(self, t: T) -> Option<T>;
54
55	fn then_async<O: Future, F: FnOnce() -> O>(self, f: F) -> OptionFuture<O>;
56
57	fn then_none<T>(self) -> Option<T>;
58
59	fn then_ok_or<T, E>(self, t: T, e: E) -> Result<T, E>;
60
61	fn then_ok_or_else<T, E, F: FnOnce() -> E>(self, t: T, e: F) -> Result<T, E>;
62}
63
64impl BoolExt for bool {
65	#[inline]
66	fn and<T>(self, t: Option<T>) -> Option<T> { self.then_some(t).flatten() }
67
68	#[inline]
69	fn and_if<F: FnOnce() -> Self>(self, f: F) -> Self { self.and_is(f()) }
70
71	#[inline]
72	fn and_is(self, b: Self) -> Self { self && b }
73
74	#[inline]
75	fn and_then<T, F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> { self.then(f).flatten() }
76
77	#[inline]
78	fn clone_or<T: Clone>(self, err: T, t: &T) -> T { self.map_or(err, || t.clone()) }
79
80	#[inline]
81	fn copy_or<T: Copy>(self, err: T, t: T) -> T { self.map_or(err, || t) }
82
83	#[inline]
84	fn expect(self, msg: &str) -> Self { self.then_some(true).expect(msg) }
85
86	#[inline]
87	fn expect_false(self, msg: &str) -> Self { self.is_false().then_some(false).expect(msg) }
88
89	#[inline]
90	fn into_option(self) -> Option<()> { self.then_some(()) }
91
92	#[inline]
93	fn into_result(self) -> Result<(), ()> { self.ok_or(()) }
94
95	#[inline]
96	fn is_false(&self) -> Self { self.eq(&false) }
97
98	#[inline]
99	fn map<T, F: FnOnce(Self) -> T>(self, f: F) -> T
100	where
101		Self: Sized,
102	{
103		f(self)
104	}
105
106	#[inline]
107	fn map_ok_or<T, E, F: FnOnce() -> T>(self, err: E, f: F) -> Result<T, E> {
108		self.ok_or(err).map(|()| f())
109	}
110
111	#[inline]
112	fn map_or<T, F: FnOnce() -> T>(self, err: T, f: F) -> T { self.then(f).unwrap_or(err) }
113
114	#[inline]
115	fn map_or_else<T, E: FnOnce() -> T, F: FnOnce() -> T>(self, err: E, f: F) -> T {
116		self.then(f).unwrap_or_else(err)
117	}
118
119	#[inline]
120	fn ok_or<E>(self, err: E) -> Result<(), E> { self.into_option().ok_or(err) }
121
122	#[inline]
123	fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<(), E> {
124		self.into_option().ok_or_else(err)
125	}
126
127	#[inline]
128	fn or<T, F: FnOnce() -> T>(self, f: F) -> Option<T> { self.is_false().then(f) }
129
130	#[inline]
131	fn or_some<T>(self, t: T) -> Option<T> { self.is_false().then_some(t) }
132
133	#[inline]
134	fn then_async<O: Future, F: FnOnce() -> O>(self, f: F) -> OptionFuture<O> {
135		OptionFuture::<_>::from(self.then(f))
136	}
137
138	#[inline]
139	fn then_none<T>(self) -> Option<T> { Option::<T>::None }
140
141	#[inline]
142	fn then_ok_or<T, E>(self, t: T, e: E) -> Result<T, E> { self.map_ok_or(e, move || t) }
143
144	#[inline]
145	fn then_ok_or_else<T, E, F: FnOnce() -> E>(self, t: T, e: F) -> Result<T, E> {
146		self.ok_or_else(e).map(move |()| t)
147	}
148}