rx_rust/operators/combining/
merge_all.rs1use crate::disposable::Disposable;
2use crate::operators::others::with_error_type::WithErrorType;
3use crate::utils::id_generator::{Id, IdGenerator};
4use crate::utils::serialized_delivery::UpdateOutcome;
5use crate::utils::subscribe_with_context::{
6 self, SubscriptionContext, subscribe_with_context_owning_source,
7};
8use crate::utils::types::MaybeSend;
9use crate::{
10 observable::{Observable, Subscription},
11 observer::{Flow, Observer, Termination},
12 operators::creating::from_iter::FromIter,
13 utils::types::MarkerType,
14};
15use educe::Educe;
16use std::collections::HashMap;
17use std::marker::PhantomData;
18
19#[derive(Educe)]
49#[educe(Debug, Clone)]
50pub struct MergeAll<OE, OE1> {
51 source: OE,
52 _marker: MarkerType<OE1>,
53}
54
55impl<OE, OE1> MergeAll<OE, OE1> {
56 pub fn new<'or, T, E>(source: OE) -> Self
57 where
58 OE: Observable<'or, OE1, E>,
59 OE1: Observable<'or, T, E>,
60 {
61 Self {
62 source,
63 _marker: PhantomData,
64 }
65 }
66}
67
68impl<E, OE1, I> MergeAll<WithErrorType<E, FromIter<I>>, OE1> {
69 pub fn new_from_iter<'or, T>(into_iterator: I) -> Self
70 where
71 I: IntoIterator<Item = OE1>,
72 OE1: Observable<'or, T, E>,
73 {
74 Self {
75 source: WithErrorType::new(FromIter::new(into_iterator)),
76 _marker: PhantomData,
77 }
78 }
79}
80
81impl<'or, T, E, OE, OE1> Observable<'or, T, E> for MergeAll<OE, OE1>
82where
83 T: MaybeSend + 'or,
84 E: MaybeSend + 'or,
85 OE: Observable<'or, OE1, E>,
86 OE::D: MaybeSend + 'or,
87 OE1: Observable<'or, T, E>,
88 OE1::D: MaybeSend + 'or,
89{
90 type D = subscribe_with_context::OwningDisposal<'or>;
91
92 fn subscribe(self, observer: impl Observer<T, E> + MaybeSend + 'or) -> Subscription<Self::D> {
93 let model = Model {
94 subscriptions: HashMap::new(),
95 keys: IdGenerator::default(),
96 is_source_terminated: false,
97 };
98 subscribe_with_context_owning_source(observer, model, |context| {
99 self.source.subscribe(MergeAllObserver(context))
100 })
101 }
102}
103
104struct Model<D: Disposable> {
105 subscriptions: HashMap<Id, Option<Subscription<D>>>,
108 keys: IdGenerator,
109 is_source_terminated: bool,
110}
111
112impl<D: Disposable> Model<D> {
113 fn insert_placeholder(&mut self) -> Id {
115 let key = self.keys.next_id();
116 self.subscriptions.insert(key, None);
117 key
118 }
119}
120
121struct MergeAllObserver<T, E, OR, ID: Disposable, SD: Disposable>(
122 SubscriptionContext<T, E, OR, Model<ID>, SD>,
123);
124
125impl<'or, T, E, OR, OE1, SD> Observer<OE1, E> for MergeAllObserver<T, E, OR, OE1::D, SD>
126where
127 T: MaybeSend + 'or,
128 E: MaybeSend + 'or,
129 OR: Observer<T, E> + MaybeSend + 'or,
130 OE1: Observable<'or, T, E>,
131 OE1::D: MaybeSend + 'or,
132 SD: Disposable + MaybeSend + 'or,
133{
134 fn on_next(&mut self, value: OE1) -> Flow {
135 let result = self
137 .0
138 .update(|model| UpdateOutcome::new(model.insert_placeholder()));
139 let key = match result {
140 Ok(key) => key,
141 Err(_) => return Flow::Stop,
142 };
143 let observer = MergeAllInnerObserver {
144 context: self.0.clone(),
145 key,
146 };
147 let sub = value.subscribe(observer);
148
149 self.0.update_flow(|model| {
150 if let Some(slot) = model.subscriptions.get_mut(&key) {
151 *slot = Some(sub);
152 UpdateOutcome::empty().without_drop_outside()
153 } else {
154 UpdateOutcome::empty().with_drop_outside(sub)
156 }
157 })
158 }
159
160 fn on_termination(self, termination: Termination<E>) {
161 match termination {
162 completion @ Termination::Completed => {
163 let _ = self.0.update(|model| {
164 if model.subscriptions.is_empty() {
165 UpdateOutcome::empty().with_termination_event(completion)
166 } else {
167 model.is_source_terminated = true;
168 UpdateOutcome::empty().without_events()
169 }
170 });
171 }
172 error @ Termination::Error(_) => {
173 self.0.send_termination(error);
174 }
175 }
176 }
177}
178
179struct MergeAllInnerObserver<T, E, OR, ID: Disposable, SD: Disposable> {
180 context: SubscriptionContext<T, E, OR, Model<ID>, SD>,
181 key: Id,
182}
183
184impl<T, E, OR, ID, SD> Observer<T, E> for MergeAllInnerObserver<T, E, OR, ID, SD>
185where
186 OR: Observer<T, E>,
187 ID: Disposable,
188 SD: Disposable,
189{
190 fn on_next(&mut self, value: T) -> Flow {
191 self.context.send_next(value)
192 }
193
194 fn on_termination(self, termination: Termination<E>) {
195 match termination {
196 completion @ Termination::Completed => {
197 let _ = self.context.update(|model| {
198 let subscription = model.subscriptions.remove(&self.key);
199 if model.is_source_terminated && model.subscriptions.is_empty() {
200 UpdateOutcome::empty()
201 .with_termination_event(completion)
202 .with_drop_outside(subscription)
203 } else {
204 UpdateOutcome::empty()
205 .without_events()
206 .with_drop_outside(subscription)
207 }
208 });
209 }
210 error @ Termination::Error(_) => {
211 self.context.send_termination(error);
212 }
213 }
214 }
215}