tuwunel_core/utils/future/
bool_ext.rs1#![expect(clippy::many_single_char_names, clippy::impl_trait_in_params)]
12
13use futures::{
14 FutureExt,
15 future::{select_ok, try_join, try_join_all, try_join3, try_join4},
16};
17
18use crate::utils::BoolExt as _;
19
20pub trait BoolExt
26where
27 Self: Future<Output = bool> + Send,
28{
29 fn or<B>(self, b: B) -> impl Future<Output = bool> + Send
36 where
37 B: Future<Output = bool> + Send + Unpin,
38 Self: Sized + Unpin;
39
40 fn and<B>(self, b: B) -> impl Future<Output = bool> + Send
45 where
46 B: Future<Output = bool> + Send,
47 Self: Sized;
48
49 fn and2<B, C>(self, b: B, c: C) -> impl Future<Output = bool> + Send
54 where
55 B: Future<Output = bool> + Send,
56 C: Future<Output = bool> + Send,
57 Self: Sized;
58
59 fn and3<B, C, D>(self, b: B, c: C, d: D) -> impl Future<Output = bool> + Send
64 where
65 B: Future<Output = bool> + Send,
66 C: Future<Output = bool> + Send,
67 D: Future<Output = bool> + Send,
68 Self: Sized;
69}
70
71impl<Fut> BoolExt for Fut
72where
73 Fut: Future<Output = bool> + Send,
74{
75 fn or<B>(self, b: B) -> impl Future<Output = bool> + Send
76 where
77 B: Future<Output = bool> + Send + Unpin,
78 Self: Sized + Unpin,
79 {
80 select_ok([self.map(test).left_future(), b.map(test).right_future()])
81 .map(|res| res.is_ok())
82 }
83
84 fn and<B>(self, b: B) -> impl Future<Output = bool> + Send
85 where
86 B: Future<Output = bool> + Send,
87 Self: Sized,
88 {
89 try_join(self.map(test), b.map(test)).map(|res| res.is_ok())
90 }
91
92 fn and2<B, C>(self, b: B, c: C) -> impl Future<Output = bool> + Send
93 where
94 B: Future<Output = bool> + Send,
95 C: Future<Output = bool> + Send,
96 Self: Sized,
97 {
98 try_join3(self.map(test), b.map(test), c.map(test)).map(|res| res.is_ok())
99 }
100
101 fn and3<B, C, D>(self, b: B, c: C, d: D) -> impl Future<Output = bool> + Send
102 where
103 B: Future<Output = bool> + Send,
104 C: Future<Output = bool> + Send,
105 D: Future<Output = bool> + Send,
106 Self: Sized,
107 {
108 try_join4(self.map(test), b.map(test), c.map(test), d.map(test)).map(|res| res.is_ok())
109 }
110}
111
112pub fn and<I, F>(args: I) -> impl Future<Output = bool> + Send
119where
120 I: Iterator<Item = F> + Send,
121 F: Future<Output = bool> + Send,
122{
123 let args = args.map(|a| a.map(test));
124
125 try_join_all(args).map(|res| res.is_ok())
126}
127
128pub fn or<I, F>(args: I) -> impl Future<Output = bool> + Send
137where
138 I: Iterator<Item = F> + Send,
139 F: Future<Output = bool> + Send + Unpin,
140{
141 let args = args.map(|a| a.map(test));
142
143 select_ok(args).map(|res| res.is_ok())
144}
145
146pub fn and4(
151 a: impl Future<Output = bool> + Send,
152 b: impl Future<Output = bool> + Send,
153 c: impl Future<Output = bool> + Send,
154 d: impl Future<Output = bool> + Send,
155) -> impl Future<Output = bool> + Send {
156 a.and3(b, c, d)
157}
158
159pub fn and5(
164 a: impl Future<Output = bool> + Send,
165 b: impl Future<Output = bool> + Send,
166 c: impl Future<Output = bool> + Send,
167 d: impl Future<Output = bool> + Send,
168 e: impl Future<Output = bool> + Send,
169) -> impl Future<Output = bool> + Send {
170 a.and2(b, c).and2(d, e)
171}
172
173pub fn and6(
178 a: impl Future<Output = bool> + Send,
179 b: impl Future<Output = bool> + Send,
180 c: impl Future<Output = bool> + Send,
181 d: impl Future<Output = bool> + Send,
182 e: impl Future<Output = bool> + Send,
183 f: impl Future<Output = bool> + Send,
184) -> impl Future<Output = bool> + Send {
185 a.and3(b, c, d).and2(e, f)
186}
187
188pub fn and7(
193 a: impl Future<Output = bool> + Send,
194 b: impl Future<Output = bool> + Send,
195 c: impl Future<Output = bool> + Send,
196 d: impl Future<Output = bool> + Send,
197 e: impl Future<Output = bool> + Send,
198 f: impl Future<Output = bool> + Send,
199 g: impl Future<Output = bool> + Send,
200) -> impl Future<Output = bool> + Send {
201 a.and3(b, c, d).and3(e, f, g)
202}
203
204fn test(test: bool) -> crate::Result<(), ()> { test.into_result() }