Skip to main content

tuwunel_core/utils/stream/
try_ready.rs

1//! Synchronous combinator extensions to futures::TryStream
2#![expect(clippy::type_complexity)]
3
4use futures::{
5	future::{Ready, ready},
6	stream::{
7		AndThen, TryFilter, TryFilterMap, TryFold, TryForEach, TrySkipWhile, TryStream,
8		TryStreamExt, TryTakeWhile,
9	},
10};
11
12use crate::Result;
13
14/// Synchronous combinators to augment futures::TryStreamExt.
15///
16/// This interface is not necessarily complete; feel free to add as-needed.
17pub trait TryReadyExt<T, E, S>
18where
19	S: TryStream<Ok = T, Error = E, Item = Result<T, E>> + ?Sized,
20	Self: TryStream + Sized,
21{
22	fn ready_and_then<U, F>(
23		self,
24		f: F,
25	) -> AndThen<Self, Ready<Result<U, E>>, impl FnMut(S::Ok) -> Ready<Result<U, E>>>
26	where
27		F: Fn(S::Ok) -> Result<U, E>;
28
29	fn ready_try_filter<F>(
30		self,
31		f: F,
32	) -> TryFilter<Self, Ready<bool>, impl FnMut(&S::Ok) -> Ready<bool>>
33	where
34		F: Fn(&S::Ok) -> bool;
35
36	fn ready_try_filter_map<F, U>(
37		self,
38		f: F,
39	) -> TryFilterMap<
40		Self,
41		Ready<Result<Option<U>, E>>,
42		impl FnMut(S::Ok) -> Ready<Result<Option<U>, E>>,
43	>
44	where
45		F: Fn(S::Ok) -> Result<Option<U>, E>;
46
47	fn ready_try_fold<U, F>(
48		self,
49		init: U,
50		f: F,
51	) -> TryFold<Self, Ready<Result<U, E>>, U, impl FnMut(U, S::Ok) -> Ready<Result<U, E>>>
52	where
53		F: Fn(U, S::Ok) -> Result<U, E>;
54
55	fn ready_try_fold_default<U, F>(
56		self,
57		f: F,
58	) -> TryFold<Self, Ready<Result<U, E>>, U, impl FnMut(U, S::Ok) -> Ready<Result<U, E>>>
59	where
60		F: Fn(U, S::Ok) -> Result<U, E>,
61		U: Default;
62
63	fn ready_try_for_each<F>(
64		self,
65		f: F,
66	) -> TryForEach<Self, Ready<Result<(), E>>, impl FnMut(S::Ok) -> Ready<Result<(), E>>>
67	where
68		F: FnMut(S::Ok) -> Result<(), E>;
69
70	fn ready_try_skip_while<F>(
71		self,
72		f: F,
73	) -> TrySkipWhile<Self, Ready<Result<bool, E>>, impl FnMut(&S::Ok) -> Ready<Result<bool, E>>>
74	where
75		F: Fn(&S::Ok) -> Result<bool, E>;
76
77	fn ready_try_take_while<F>(
78		self,
79		f: F,
80	) -> TryTakeWhile<Self, Ready<Result<bool, E>>, impl FnMut(&S::Ok) -> Ready<Result<bool, E>>>
81	where
82		F: Fn(&S::Ok) -> Result<bool, E>;
83}
84
85impl<T, E, S> TryReadyExt<T, E, S> for S
86where
87	S: TryStream<Ok = T, Error = E, Item = Result<T, E>> + ?Sized,
88	Self: TryStream + Sized,
89{
90	#[inline]
91	fn ready_and_then<U, F>(
92		self,
93		f: F,
94	) -> AndThen<Self, Ready<Result<U, E>>, impl FnMut(S::Ok) -> Ready<Result<U, E>>>
95	where
96		F: Fn(S::Ok) -> Result<U, E>,
97	{
98		self.and_then(move |t| ready(f(t)))
99	}
100
101	#[inline]
102	fn ready_try_filter<F>(
103		self,
104		f: F,
105	) -> TryFilter<Self, Ready<bool>, impl FnMut(&S::Ok) -> Ready<bool>>
106	where
107		F: Fn(&S::Ok) -> bool,
108	{
109		self.try_filter(move |t| ready(f(t)))
110	}
111
112	#[inline]
113	fn ready_try_filter_map<F, U>(
114		self,
115		f: F,
116	) -> TryFilterMap<
117		Self,
118		Ready<Result<Option<U>, E>>,
119		impl FnMut(S::Ok) -> Ready<Result<Option<U>, E>>,
120	>
121	where
122		F: Fn(S::Ok) -> Result<Option<U>, E>,
123	{
124		self.try_filter_map(move |t| ready(f(t)))
125	}
126
127	#[inline]
128	fn ready_try_fold<U, F>(
129		self,
130		init: U,
131		f: F,
132	) -> TryFold<Self, Ready<Result<U, E>>, U, impl FnMut(U, S::Ok) -> Ready<Result<U, E>>>
133	where
134		F: Fn(U, S::Ok) -> Result<U, E>,
135	{
136		self.try_fold(init, move |a, t| ready(f(a, t)))
137	}
138
139	#[inline]
140	fn ready_try_fold_default<U, F>(
141		self,
142		f: F,
143	) -> TryFold<Self, Ready<Result<U, E>>, U, impl FnMut(U, S::Ok) -> Ready<Result<U, E>>>
144	where
145		F: Fn(U, S::Ok) -> Result<U, E>,
146		U: Default,
147	{
148		self.ready_try_fold(U::default(), f)
149	}
150
151	#[inline]
152	fn ready_try_for_each<F>(
153		self,
154		mut f: F,
155	) -> TryForEach<Self, Ready<Result<(), E>>, impl FnMut(S::Ok) -> Ready<Result<(), E>>>
156	where
157		F: FnMut(S::Ok) -> Result<(), E>,
158	{
159		self.try_for_each(move |t| ready(f(t)))
160	}
161
162	#[inline]
163	fn ready_try_skip_while<F>(
164		self,
165		f: F,
166	) -> TrySkipWhile<Self, Ready<Result<bool, E>>, impl FnMut(&S::Ok) -> Ready<Result<bool, E>>>
167	where
168		F: Fn(&S::Ok) -> Result<bool, E>,
169	{
170		self.try_skip_while(move |t| ready(f(t)))
171	}
172
173	#[inline]
174	fn ready_try_take_while<F>(
175		self,
176		f: F,
177	) -> TryTakeWhile<Self, Ready<Result<bool, E>>, impl FnMut(&S::Ok) -> Ready<Result<bool, E>>>
178	where
179		F: Fn(&S::Ok) -> Result<bool, E>,
180	{
181		self.try_take_while(move |t| ready(f(t)))
182	}
183}