1use crate::{Stop, StopReason};
24
25#[derive(Debug, Clone, Copy)]
47pub struct OrStop<A, B> {
48 a: A,
49 b: B,
50}
51
52impl<A, B> OrStop<A, B> {
53 #[inline]
55 pub fn new(a: A, b: B) -> Self {
56 Self { a, b }
57 }
58
59 #[inline]
61 pub fn first(&self) -> &A {
62 &self.a
63 }
64
65 #[inline]
67 pub fn second(&self) -> &B {
68 &self.b
69 }
70
71 #[inline]
73 pub fn into_inner(self) -> (A, B) {
74 (self.a, self.b)
75 }
76}
77
78impl<A: Stop, B: Stop> Stop for OrStop<A, B> {
79 #[inline]
80 fn check(&self) -> Result<(), StopReason> {
81 self.a.check()?;
82 self.b.check()
83 }
84
85 #[inline]
86 fn should_stop(&self) -> bool {
87 self.a.should_stop() || self.b.should_stop()
88 }
89
90 #[inline]
93 fn may_stop(&self) -> bool {
94 self.a.may_stop() || self.b.may_stop()
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101 use crate::{StopSource, Unstoppable};
102
103 #[test]
104 fn or_stop_neither() {
105 let a = StopSource::new();
106 let b = StopSource::new();
107 let combined = OrStop::new(a.as_ref(), b.as_ref());
108
109 assert!(!combined.should_stop());
110 assert!(combined.check().is_ok());
111 }
112
113 #[test]
114 fn or_stop_first() {
115 let a = StopSource::new();
116 let b = StopSource::new();
117 let combined = OrStop::new(a.as_ref(), b.as_ref());
118
119 a.cancel();
120
121 assert!(combined.should_stop());
122 assert_eq!(combined.check(), Err(StopReason::Cancelled));
123 }
124
125 #[test]
126 fn or_stop_second() {
127 let a = StopSource::new();
128 let b = StopSource::new();
129 let combined = OrStop::new(a.as_ref(), b.as_ref());
130
131 b.cancel();
132
133 assert!(combined.should_stop());
134 assert_eq!(combined.check(), Err(StopReason::Cancelled));
135 }
136
137 #[test]
138 fn or_stop_both() {
139 let a = StopSource::new();
140 let b = StopSource::new();
141 let combined = OrStop::new(a.as_ref(), b.as_ref());
142
143 a.cancel();
144 b.cancel();
145
146 assert!(combined.should_stop());
147 }
148
149 #[test]
150 fn or_stop_chain() {
151 let a = StopSource::new();
152 let b = StopSource::new();
153 let c = StopSource::new();
154
155 let combined = OrStop::new(OrStop::new(a.as_ref(), b.as_ref()), c.as_ref());
156
157 assert!(!combined.should_stop());
158
159 c.cancel();
160 assert!(combined.should_stop());
161 }
162
163 #[test]
164 fn or_stop_with_unstoppable() {
165 let source = StopSource::new();
166 let combined = OrStop::new(Unstoppable, source.as_ref());
167
168 assert!(!combined.should_stop());
169
170 source.cancel();
171 assert!(combined.should_stop());
172 }
173
174 #[test]
175 fn or_stop_is_send_sync() {
176 fn assert_send_sync<T: Send + Sync>() {}
177 assert_send_sync::<OrStop<crate::StopRef<'_>, crate::StopRef<'_>>>();
178 }
179
180 #[test]
181 fn or_stop_accessors() {
182 let a = StopSource::new();
183 let b = StopSource::new();
184 let combined = OrStop::new(a.as_ref(), b.as_ref());
185
186 assert!(!combined.first().should_stop());
187 assert!(!combined.second().should_stop());
188
189 a.cancel();
190 assert!(combined.first().should_stop());
191
192 let (first, second) = combined.into_inner();
193 assert!(first.should_stop());
194 assert!(!second.should_stop());
195 }
196
197 #[test]
198 fn or_stop_ref_is_copy() {
199 let a = StopSource::new();
201 let b = StopSource::new();
202 let combined = OrStop::new(a.as_ref(), b.as_ref());
203 let combined2 = combined; a.cancel();
206 assert!(combined.should_stop()); assert!(combined2.should_stop());
208 }
209
210 #[test]
211 fn or_stop_is_copy() {
212 let a = StopSource::new();
213 let b = StopSource::new();
214 let combined = OrStop::new(a.as_ref(), b.as_ref());
215 let combined2 = combined; let _ = combined; assert!(!combined2.should_stop());
219 }
220
221 #[test]
222 fn may_stop_both_unstoppable() {
223 let combined = OrStop::new(Unstoppable, Unstoppable);
224 assert!(!combined.may_stop());
225 }
226
227 #[test]
228 fn may_stop_one_side() {
229 let source = StopSource::new();
230 let combined = OrStop::new(Unstoppable, source.as_ref());
231 assert!(combined.may_stop());
232 }
233
234 #[test]
235 fn may_stop_both_sides() {
236 let a = StopSource::new();
237 let b = StopSource::new();
238 let combined = OrStop::new(a.as_ref(), b.as_ref());
239 assert!(combined.may_stop());
240 }
241}