tuwunel_core/utils/future/
bool_ext.rs1#![expect(clippy::many_single_char_names, clippy::impl_trait_in_params)]
3
4use futures::{
5 FutureExt,
6 future::{
7 Either::{Left, Right},
8 select_ok, try_join, try_join_all, try_join3, try_join4,
9 },
10};
11
12use crate::utils::BoolExt as _;
13
14pub trait BoolExt
20where
21 Self: Future<Output = bool> + Send,
22{
23 fn or<B>(self, b: B) -> impl Future<Output = bool> + Send
28 where
29 B: Future<Output = bool> + Send + Unpin,
30 Self: Sized + Unpin;
31
32 fn and<B>(self, b: B) -> impl Future<Output = bool> + Send
37 where
38 B: Future<Output = bool> + Send,
39 Self: Sized;
40
41 fn and2<B, C>(self, b: B, c: C) -> impl Future<Output = bool> + Send
46 where
47 B: Future<Output = bool> + Send,
48 C: Future<Output = bool> + Send,
49 Self: Sized;
50
51 fn and3<B, C, D>(self, b: B, c: C, d: D) -> impl Future<Output = bool> + Send
56 where
57 B: Future<Output = bool> + Send,
58 C: Future<Output = bool> + Send,
59 D: Future<Output = bool> + Send,
60 Self: Sized;
61}
62
63impl<Fut> BoolExt for Fut
64where
65 Fut: Future<Output = bool> + Send,
66{
67 fn or<B>(self, b: B) -> impl Future<Output = bool> + Send
68 where
69 B: Future<Output = bool> + Send + Unpin,
70 Self: Sized + Unpin,
71 {
72 select_ok([Left(self.map(test)), Right(b.map(test))]).map(|res| res.is_ok())
73 }
74
75 fn and<B>(self, b: B) -> impl Future<Output = bool> + Send
76 where
77 B: Future<Output = bool> + Send,
78 Self: Sized,
79 {
80 try_join(self.map(test), b.map(test)).map(|res| res.is_ok())
81 }
82
83 fn and2<B, C>(self, b: B, c: C) -> impl Future<Output = bool> + Send
84 where
85 B: Future<Output = bool> + Send,
86 C: Future<Output = bool> + Send,
87 Self: Sized,
88 {
89 try_join3(self.map(test), b.map(test), c.map(test)).map(|res| res.is_ok())
90 }
91
92 fn and3<B, C, D>(self, b: B, c: C, d: D) -> impl Future<Output = bool> + Send
93 where
94 B: Future<Output = bool> + Send,
95 C: Future<Output = bool> + Send,
96 D: Future<Output = bool> + Send,
97 Self: Sized,
98 {
99 try_join4(self.map(test), b.map(test), c.map(test), d.map(test)).map(|res| res.is_ok())
100 }
101}
102
103pub fn and<I, F>(args: I) -> impl Future<Output = bool> + Send
108where
109 I: Iterator<Item = F> + Send,
110 F: Future<Output = bool> + Send,
111{
112 let args = args.map(|a| a.map(test));
113
114 try_join_all(args).map(|res| res.is_ok())
115}
116
117pub fn or<I, F>(args: I) -> impl Future<Output = bool> + Send
126where
127 I: Iterator<Item = F> + Send,
128 F: Future<Output = bool> + Send + Unpin,
129{
130 let args = args.map(|a| a.map(test));
131
132 select_ok(args).map(|res| res.is_ok())
133}
134
135pub fn and4(
140 a: impl Future<Output = bool> + Send,
141 b: impl Future<Output = bool> + Send,
142 c: impl Future<Output = bool> + Send,
143 d: impl Future<Output = bool> + Send,
144) -> impl Future<Output = bool> + Send {
145 a.and3(b, c, d)
146}
147
148pub fn and5(
153 a: impl Future<Output = bool> + Send,
154 b: impl Future<Output = bool> + Send,
155 c: impl Future<Output = bool> + Send,
156 d: impl Future<Output = bool> + Send,
157 e: impl Future<Output = bool> + Send,
158) -> impl Future<Output = bool> + Send {
159 a.and2(b, c).and2(d, e)
160}
161
162pub fn and6(
167 a: impl Future<Output = bool> + Send,
168 b: impl Future<Output = bool> + Send,
169 c: impl Future<Output = bool> + Send,
170 d: impl Future<Output = bool> + Send,
171 e: impl Future<Output = bool> + Send,
172 f: impl Future<Output = bool> + Send,
173) -> impl Future<Output = bool> + Send {
174 a.and3(b, c, d).and2(e, f)
175}
176
177pub fn and7(
182 a: impl Future<Output = bool> + Send,
183 b: impl Future<Output = bool> + Send,
184 c: impl Future<Output = bool> + Send,
185 d: impl Future<Output = bool> + Send,
186 e: impl Future<Output = bool> + Send,
187 f: impl Future<Output = bool> + Send,
188 g: impl Future<Output = bool> + Send,
189) -> impl Future<Output = bool> + Send {
190 a.and3(b, c, d).and3(e, f, g)
191}
192
193fn test(test: bool) -> crate::Result<(), ()> { test.into_result() }