Skip to main content

zrx_stream/stream/combinator/tuple/
ext.rs

1// Copyright (c) 2025-2026 Zensical and contributors
2
3// SPDX-License-Identifier: MIT
4// All contributions are certified under the DCO
5
6// Permission is hereby granted, free of charge, to any person obtaining a copy
7// of this software and associated documentation files (the "Software"), to
8// deal in the Software without restriction, including without limitation the
9// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10// sell copies of the Software, and to permit persons to whom the Software is
11// furnished to do so, subject to the following conditions:
12
13// The above copyright notice and this permission notice shall be included in
14// all copies or substantial portions of the Software.
15
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22// IN THE SOFTWARE.
23
24// ----------------------------------------------------------------------------
25
26//! Stream tuple extensions.
27
28use zrx_scheduler::{Id, Value};
29
30use crate::stream::combinator::tuple::join::{
31    IntoJoin, IntoJoinFilter, IntoJoinFilterMap, IntoJoinMap,
32};
33use crate::stream::function::{FilterFn, FilterMapFn, MapFn, Splat};
34use crate::stream::value::tuple::{All, Any, First};
35use crate::stream::Stream;
36
37use super::convert::IntoStreamTuple;
38
39// ----------------------------------------------------------------------------
40// Traits
41// ----------------------------------------------------------------------------
42
43/// Extension of [`StreamTuple`][].
44///
45/// While conceptually, this extension trait does belong to [`StreamTuple`][],
46/// allowing to conveniently work with data types that can be converted into a
47/// tuple of streams, it is deliberately implemented for anything that converts
48/// via [`IntoStreamTuple`], as this offers more flexibilty.
49///
50/// [`StreamTuple`]: crate::stream::combinator::StreamTuple
51pub trait StreamTupleExt<I, S>: IntoStreamTuple<I, Output = S> + Sized
52where
53    I: Id,
54{
55    fn join(self) -> Stream<I, S::Item>
56    where
57        S: IntoJoin<I, All>,
58    {
59        self.into_stream_tuple() // fmt
60            .into_join()
61    }
62
63    fn join_filter<F>(self, f: F) -> Stream<I, S::Item>
64    where
65        S: IntoJoinFilter<I, All>,
66        F: FilterFn<I, Splat<S::Item>> + Clone,
67    {
68        self.into_stream_tuple() // fmt
69            .into_join_filter(f)
70    }
71
72    fn join_filter_map<F, U>(self, f: F) -> Stream<I, U>
73    where
74        S: IntoJoinFilterMap<I, All>,
75        F: FilterMapFn<I, Splat<S::Item>, U> + Clone,
76        U: Value,
77    {
78        self.into_stream_tuple() // fmt
79            .into_join_filter_map(f)
80    }
81
82    fn join_map<F, U>(self, f: F) -> Stream<I, U>
83    where
84        S: IntoJoinMap<I, All>,
85        F: MapFn<I, Splat<S::Item>, U> + Clone,
86        U: Value,
87    {
88        self.into_stream_tuple() // fmt
89            .into_join_map(f)
90    }
91
92    fn left_join(self) -> Stream<I, S::Item>
93    where
94        S: IntoJoin<I, First>,
95    {
96        self.into_stream_tuple() // fmt
97            .into_join()
98    }
99
100    fn left_join_filter<F>(self, f: F) -> Stream<I, S::Item>
101    where
102        S: IntoJoinFilter<I, First>,
103        F: FilterFn<I, Splat<S::Item>> + Clone,
104    {
105        self.into_stream_tuple() // fmt
106            .into_join_filter(f)
107    }
108
109    fn left_join_filter_map<F, U>(self, f: F) -> Stream<I, U>
110    where
111        S: IntoJoinFilterMap<I, First>,
112        F: FilterMapFn<I, Splat<S::Item>, U> + Clone,
113        U: Value,
114    {
115        self.into_stream_tuple() // fmt
116            .into_join_filter_map(f)
117    }
118
119    fn left_join_map<F, U>(self, f: F) -> Stream<I, U>
120    where
121        S: IntoJoinMap<I, First>,
122        F: MapFn<I, Splat<S::Item>, U> + Clone,
123        U: Value,
124    {
125        self.into_stream_tuple() // fmt
126            .into_join_map(f)
127    }
128
129    fn full_join(self) -> Stream<I, S::Item>
130    where
131        S: IntoJoin<I, Any>,
132    {
133        self.into_stream_tuple() // fmt
134            .into_join()
135    }
136
137    fn full_join_filter<F>(self, f: F) -> Stream<I, S::Item>
138    where
139        S: IntoJoinFilter<I, Any>,
140        F: FilterFn<I, Splat<S::Item>> + Clone,
141    {
142        self.into_stream_tuple() // fmt
143            .into_join_filter(f)
144    }
145
146    fn full_join_filter_map<F, U>(self, f: F) -> Stream<I, U>
147    where
148        S: IntoJoinFilterMap<I, Any>,
149        F: FilterMapFn<I, Splat<S::Item>, U> + Clone,
150        U: Value,
151    {
152        self.into_stream_tuple() // fmt
153            .into_join_filter_map(f)
154    }
155
156    fn full_join_map<F, U>(self, f: F) -> Stream<I, U>
157    where
158        S: IntoJoinMap<I, Any>,
159        F: MapFn<I, Splat<S::Item>, U> + Clone,
160        U: Value,
161    {
162        self.into_stream_tuple() // fmt
163            .into_join_map(f)
164    }
165}
166
167// ----------------------------------------------------------------------------
168// Blanket implementations
169// ----------------------------------------------------------------------------
170
171impl<T, I, S> StreamTupleExt<I, S> for T
172where
173    I: Id,
174    T: IntoStreamTuple<I, Output = S>,
175{
176}