rx_rust/operators/conditional_boolean/
sequence_equal.rs1use crate::utils::serialized_delivery::UpdateOutcome;
2use crate::utils::subscribe_with_context::{
3 self, SubscriptionContext, subscribe_with_context_owning_source,
4};
5use crate::utils::types::{MarkerType, MaybeSend};
6use crate::{
7 disposable::Disposable,
8 observable::{Observable, Subscription},
9 observer::{Flow, Observer, Termination},
10};
11use educe::Educe;
12use std::collections::VecDeque;
13use std::marker::PhantomData;
14
15#[derive(Educe)]
45#[educe(Debug, Clone)]
46pub struct SequenceEqual<T, OE1, OE2> {
47 source_1: OE1,
48 source_2: OE2,
49 _marker: MarkerType<T>,
50}
51
52impl<T, OE1, OE2> SequenceEqual<T, OE1, OE2> {
53 pub fn new<'or, E>(source_1: OE1, source_2: OE2) -> Self
54 where
55 OE1: Observable<'or, T, E>,
56 OE2: Observable<'or, T, E>,
57 {
58 Self {
59 source_1,
60 source_2,
61 _marker: PhantomData,
62 }
63 }
64}
65
66impl<'or, T, E, OE1, OE2> Observable<'or, bool, E> for SequenceEqual<T, OE1, OE2>
67where
68 T: PartialEq + MaybeSend + 'or,
69 E: MaybeSend + 'or,
70 OE1: Observable<'or, T, E>,
71 OE1::D: MaybeSend + 'or,
72 OE2: Observable<'or, T, E>,
73 OE2::D: MaybeSend + 'or,
74{
75 type D = subscribe_with_context::OwningDisposal<'or>;
76
77 fn subscribe(
78 self,
79 observer: impl Observer<bool, E> + MaybeSend + 'or,
80 ) -> Subscription<Self::D> {
81 let model = Model {
82 first: SourceState {
83 queue: VecDeque::new(),
84 completed: false,
85 },
86 second: SourceState {
87 queue: VecDeque::new(),
88 completed: false,
89 },
90 };
91 subscribe_with_context_owning_source(observer, model, |context| {
92 let observer_1 = SequenceEqualObserver {
93 context: context.clone(),
94 is_first: true,
95 };
96 let observer_2 = SequenceEqualObserver {
97 context,
98 is_first: false,
99 };
100 let subscription_1 = self.source_1.subscribe(observer_1);
101 let subscription_2 = self.source_2.subscribe(observer_2);
102 subscription_1.preceded_by_bound(subscription_2)
103 })
104 }
105}
106
107struct SourceState<T> {
108 queue: VecDeque<T>,
109 completed: bool,
110}
111
112struct Model<T> {
113 first: SourceState<T>,
114 second: SourceState<T>,
115}
116
117struct SequenceEqualObserver<T, E, OR, D: Disposable> {
118 context: SubscriptionContext<bool, E, OR, Model<T>, D>,
119 is_first: bool,
120}
121
122impl<T, E, OR, D> Observer<T, E> for SequenceEqualObserver<T, E, OR, D>
123where
124 OR: Observer<bool, E>,
125 T: PartialEq,
126 D: Disposable,
127{
128 fn on_next(&mut self, value: T) -> Flow {
129 self.context.update_flow(|model| {
130 let (mine, other) = if self.is_first {
131 (&mut model.first, &mut model.second)
132 } else {
133 (&mut model.second, &mut model.first)
134 };
135
136 match (other.queue.pop_front(), other.completed) {
137 (None, true) => UpdateOutcome::empty()
140 .with_drop_outside((Some(value), None))
141 .with_next_and_termination_events(false, Termination::Completed),
142 (None, false) => {
143 mine.queue.push_back(value);
144 UpdateOutcome::empty()
145 .without_drop_outside()
146 .without_events()
147 }
148 (Some(next), _) => {
149 let is_equal = value == next;
153 let outcome =
154 UpdateOutcome::empty().with_drop_outside((Some(value), Some(next)));
155 if is_equal {
156 outcome.without_events()
157 } else {
158 outcome.with_next_and_termination_events(false, Termination::Completed)
159 }
160 }
161 }
162 })
163 }
164
165 fn on_termination(self, termination: Termination<E>) {
166 match termination {
167 completion @ Termination::Completed => {
168 let _ = self.context.update(|model| {
169 let (mine, other) = if self.is_first {
170 (&mut model.first, &mut model.second)
171 } else {
172 (&mut model.second, &mut model.first)
173 };
174 mine.completed = true;
175
176 let mine_empty = mine.queue.is_empty();
177 let other_completed = other.completed;
178 let other_empty = other.queue.is_empty();
179
180 if !other_completed && other_empty {
181 UpdateOutcome::empty().without_events()
182 } else {
183 let is_equal = mine_empty && other_completed && other_empty;
184 UpdateOutcome::empty()
185 .with_next_and_termination_events(is_equal, completion)
186 }
187 });
188 }
189 error @ Termination::Error(_) => {
190 self.context.send_termination(error);
191 }
192 };
193 }
194}