Skip to main content

tuwunel_core/utils/stream/
ignore.rs

1use futures::{Stream, StreamExt, TryStream, future::ready};
2
3use crate::{Error, Result, utils::stream::TryExpect};
4
5/// Selects successful or failed items from a result stream.
6///
7/// Success selection asserts error-free input when debug assertions are enabled
8/// and filters errors when they are disabled. Error selection always discards
9/// successful items.
10pub trait TryIgnore<Item>
11where
12	Item: Send,
13	Self: Send + Sized,
14{
15	/// Yields successful values while conditionally ignoring errors.
16	///
17	/// Errors are filtered when debug assertions are disabled. When they are
18	/// enabled, each item is expected to be successful so accidental error loss
19	/// remains visible.
20	///
21	/// # Panics
22	///
23	/// Panics when debug assertions are enabled and the source yields an error.
24	fn ignore_err(self) -> impl Stream<Item = Item> + Send;
25
26	/// Yields errors while ignoring successful values.
27	///
28	/// Successful items are filtered out as the stream is polled. Errors retain
29	/// their source order and value.
30	fn ignore_ok(self) -> impl Stream<Item = Error> + Send;
31}
32
33impl<Item, S> TryIgnore<Item> for S
34where
35	S: Stream<Item = Result<Item>> + Send + TryStream + TryExpect<Item>,
36	Item: Send,
37	Self: Send + Sized,
38{
39	#[cfg(debug_assertions)]
40	#[inline]
41	fn ignore_err(self: S) -> impl Stream<Item = Item> + Send { self.expect_ok() }
42
43	#[cfg(not(debug_assertions))]
44	#[inline]
45	fn ignore_err(self: S) -> impl Stream<Item = Item> + Send {
46		self.filter_map(|res| ready(res.ok()))
47	}
48
49	#[inline]
50	fn ignore_ok(self: S) -> impl Stream<Item = Error> + Send {
51		self.filter_map(|res| ready(res.err()))
52	}
53}