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
91#[cfg(test)]
92mod tests {
93 use super::*;
94 use crate::{Never, StopSource};
95
96 #[test]
97 fn or_stop_neither() {
98 let a = StopSource::new();
99 let b = StopSource::new();
100 let combined = OrStop::new(a.as_ref(), b.as_ref());
101
102 assert!(!combined.should_stop());
103 assert!(combined.check().is_ok());
104 }
105
106 #[test]
107 fn or_stop_first() {
108 let a = StopSource::new();
109 let b = StopSource::new();
110 let combined = OrStop::new(a.as_ref(), b.as_ref());
111
112 a.cancel();
113
114 assert!(combined.should_stop());
115 assert_eq!(combined.check(), Err(StopReason::Cancelled));
116 }
117
118 #[test]
119 fn or_stop_second() {
120 let a = StopSource::new();
121 let b = StopSource::new();
122 let combined = OrStop::new(a.as_ref(), b.as_ref());
123
124 b.cancel();
125
126 assert!(combined.should_stop());
127 assert_eq!(combined.check(), Err(StopReason::Cancelled));
128 }
129
130 #[test]
131 fn or_stop_both() {
132 let a = StopSource::new();
133 let b = StopSource::new();
134 let combined = OrStop::new(a.as_ref(), b.as_ref());
135
136 a.cancel();
137 b.cancel();
138
139 assert!(combined.should_stop());
140 }
141
142 #[test]
143 fn or_stop_chain() {
144 let a = StopSource::new();
145 let b = StopSource::new();
146 let c = StopSource::new();
147
148 let combined = OrStop::new(OrStop::new(a.as_ref(), b.as_ref()), c.as_ref());
149
150 assert!(!combined.should_stop());
151
152 c.cancel();
153 assert!(combined.should_stop());
154 }
155
156 #[test]
157 fn or_stop_with_never() {
158 let source = StopSource::new();
159 let combined = OrStop::new(Never, source.as_ref());
160
161 assert!(!combined.should_stop());
162
163 source.cancel();
164 assert!(combined.should_stop());
165 }
166
167 #[test]
168 fn or_stop_is_send_sync() {
169 fn assert_send_sync<T: Send + Sync>() {}
170 assert_send_sync::<OrStop<crate::StopRef<'_>, crate::StopRef<'_>>>();
171 }
172
173 #[test]
174 fn or_stop_accessors() {
175 let a = StopSource::new();
176 let b = StopSource::new();
177 let combined = OrStop::new(a.as_ref(), b.as_ref());
178
179 assert!(!combined.first().should_stop());
180 assert!(!combined.second().should_stop());
181
182 a.cancel();
183 assert!(combined.first().should_stop());
184
185 let (first, second) = combined.into_inner();
186 assert!(first.should_stop());
187 assert!(!second.should_stop());
188 }
189
190 #[test]
191 fn or_stop_is_clone() {
192 let a = StopSource::new();
193 let b = StopSource::new();
194 let combined = OrStop::new(a.as_ref(), b.as_ref());
195 let combined2 = combined.clone();
196
197 a.cancel();
198 assert!(combined.should_stop());
199 assert!(combined2.should_stop());
200 }
201
202 #[test]
203 fn or_stop_is_copy() {
204 let a = StopSource::new();
205 let b = StopSource::new();
206 let combined = OrStop::new(a.as_ref(), b.as_ref());
207 let combined2 = combined; let _ = combined; assert!(!combined2.should_stop());
211 }
212}