1use std::{
2 cell::{Ref, RefCell, RefMut},
3 ops::{BitOr, BitOrAssign},
4 rc::Rc,
5};
6
7use log::trace;
8
9pub use crate::loop_logic::EventIterator;
10use crate::{sys::TokenFactory, Poll, Readiness, RegistrationToken, Token};
11
12pub mod channel;
13#[cfg(feature = "executor")]
14#[cfg_attr(docsrs, doc(cfg(feature = "executor")))]
15pub mod futures;
16pub mod generic;
17pub mod ping;
18#[cfg(all(target_os = "linux", feature = "signals"))]
19#[cfg_attr(docsrs, doc(cfg(target_os = "linux")))]
20pub mod signals;
21pub mod timer;
22pub mod transient;
23
24/// Possible actions that can be requested to the event loop by an
25/// event source once its events have been processed.
26///
27/// `PostAction` values can be combined with the `|` (bit-or) operator (or with
28/// `|=`) with the result that:
29/// - if both values are identical, the result is that value
30/// - if they are different, the result is [`Reregister`](PostAction::Reregister)
31///
32/// Bit-or-ing these results is useful for composed sources to combine the
33/// results of their child sources, but note that it only applies to the child
34/// sources. For example, if every child source returns `Continue`, the result
35/// will be `Continue`, but the parent source might still need to return
36/// `Reregister` or something else depending on any additional logic it uses.
37#[derive(Copy, Clone, Debug, PartialEq, Eq)]
38pub enum PostAction {
39 /// Continue listening for events on this source as before
40 Continue,
41 /// Trigger a re-registration of this source
42 Reregister,
43 /// Disable this source
44 ///
45 /// Has the same effect as [`LoopHandle::disable`](crate::LoopHandle#method.disable)
46 Disable,
47 /// Remove this source from the eventloop
48 ///
49 /// Has the same effect as [`LoopHandle::kill`](crate::LoopHandle#method.kill)
50 Remove,
51}
52
53/// Combines `PostAction` values returned from nested event sources.
54impl BitOr for PostAction {
55 type Output = Self;
56
57 fn bitor(self, rhs: Self) -> Self::Output {
58 if matches!(self, x if x == rhs) {
59 self
60 } else {
61 Self::Reregister
62 }
63 }
64}
65
66/// Combines `PostAction` values returned from nested event sources.
67impl BitOrAssign for PostAction {
68 fn bitor_assign(&mut self, rhs: Self) {
69 if *self != rhs {
70 *self = Self::Reregister;
71 }
72 }
73}
74
75/// Trait representing an event source
76///
77/// This is the trait you need to implement if you wish to create your own
78/// calloop-compatible event sources.
79///
80/// The 3 associated types define the type of closure the user will need to
81/// provide to process events for your event source.
82///
83/// The `process_events` method will be called when one of the FD you registered
84/// is ready, with the associated readiness and token.
85///
86/// The `register`, `reregister` and `unregister` methods are plumbing to let your
87/// source register itself with the polling system. See their documentation for details.
88///
89/// In case your event source needs to do some special processing before or after a
90/// polling session occurs (to prepare the underlying source for polling, and cleanup
91/// after that), you can override [`NEEDS_EXTRA_LIFECYCLE_EVENTS`] to `true`.
92/// For all sources for which that constant is `true`, the methods [`before_sleep`] and
93/// [`before_handle_events`] will be called.
94/// [`before_sleep`] is called before the polling system performs a poll operation.
95/// [`before_handle_events`] is called before any process_events methods have been called.
96/// This means that during `process_events` you can assume that all cleanup has occured on
97/// all sources.
98///
99/// [`NEEDS_EXTRA_LIFECYCLE_EVENTS`]: EventSource::NEEDS_EXTRA_LIFECYCLE_EVENTS
100/// [`before_sleep`]: EventSource::before_sleep
101/// [`before_handle_events`]: EventSource::before_handle_events
102pub trait EventSource {
103 /// The type of events generated by your source.
104 type Event;
105 /// Some metadata of your event source
106 ///
107 /// This is typically useful if your source contains some internal state that
108 /// the user may need to interact with when processing events. The user callback
109 /// will receive a `&mut Metadata` reference.
110 ///
111 /// Set to `()` if not needed.
112 type Metadata;
113 /// The return type of the user callback
114 ///
115 /// If the user needs to return some value back to your event source once its
116 /// processing is finshed (to indicate success or failure for example), you can
117 /// specify it using this type.
118 ///
119 /// Set to `()` if not needed.
120 type Ret;
121 /// The error type returned from
122 /// [`process_events()`](Self::process_events()) (not the user callback!).
123 type Error: Into<Box<dyn std::error::Error + Sync + Send>>;
124
125 /// Process any relevant events
126 ///
127 /// This method will be called every time one of the FD you registered becomes
128 /// ready, including the readiness details and the associated token.
129 ///
130 /// Your event source will then do some processing of the file descriptor(s) to generate
131 /// events, and call the provided `callback` for each one of them.
132 ///
133 /// You should ensure you drained the file descriptors of their events, especially if using
134 /// edge-triggered mode.
135 fn process_events<F>(
136 &mut self,
137 readiness: Readiness,
138 token: Token,
139 callback: F,
140 ) -> Result<PostAction, Self::Error>
141 where
142 F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret;
143
144 /// Register yourself to this poll instance
145 ///
146 /// You should register all your relevant file descriptors to the provided [`Poll`](crate::Poll)
147 /// using its [`Poll::register`](crate::Poll#method.register) method.
148 ///
149 /// If you need to register more than one file descriptor, you can change the
150 /// `sub_id` field of the [`Token`](crate::Token) to differentiate between them.
151 fn register(&mut self, poll: &mut Poll, token_factory: &mut TokenFactory) -> crate::Result<()>;
152
153 /// Re-register your file descriptors
154 ///
155 /// Your should update the registration of all your relevant file descriptor to
156 /// the provided [`Poll`](crate::Poll) using its [`Poll::reregister`](crate::Poll#method.reregister),
157 /// if necessary.
158 fn reregister(
159 &mut self,
160 poll: &mut Poll,
161 token_factory: &mut TokenFactory,
162 ) -> crate::Result<()>;
163
164 /// Unregister your file descriptors
165 ///
166 /// You should unregister all your file descriptors from this [`Poll`](crate::Poll) using its
167 /// [`Poll::unregister`](crate::Poll#method.unregister) method.
168 fn unregister(&mut self, poll: &mut Poll) -> crate::Result<()>;
169
170 /// Whether this source needs to be sent the [`EventSource::before_sleep`]
171 /// and [`EventSource::before_handle_events`] notifications. These are opt-in because
172 /// they require more expensive checks, and almost all sources will not need these notifications
173 const NEEDS_EXTRA_LIFECYCLE_EVENTS: bool = false;
174 /// Notification that a single `poll` is about to begin
175 ///
176 /// Use this to perform operations which must be done before polling,
177 /// but which may conflict with other event handlers. For example,
178 /// if polling requires a lock to be taken
179 ///
180 /// If this returns Ok(Some), this will be treated as an event arriving in polling, and
181 /// your event handler will be called with the returned `Token` and `Readiness`.
182 /// Polling will however still occur, but with a timeout of 0, so additional events
183 /// from this or other sources may also be handled in the same iterations.
184 /// The returned `Token` must belong to this source
185 // If you need to return multiple synthetic events from this notification, please
186 // open an issue
187 fn before_sleep(&mut self) -> crate::Result<Option<(Readiness, Token)>> {
188 Ok(None)
189 }
190 /// Notification that polling is complete, and [`EventSource::process_events`] will
191 /// be called with the given events for this source. The iterator may be empty,
192 /// which indicates that no events were generated for this source
193 ///
194 /// Please note, the iterator excludes any synthetic events returned from
195 /// [`EventSource::before_sleep`]
196 ///
197 /// Use this to perform a cleanup before event handlers with arbitrary
198 /// code may run. This could be used to drop a lock obtained in
199 /// [`EventSource::before_sleep`]
200 #[allow(unused_variables)]
201 fn before_handle_events(&mut self, events: EventIterator<'_>) {}
202}
203
204/// Blanket implementation for boxed event sources. [`EventSource`] is not an
205/// object safe trait, so this does not include trait objects.
206impl<T: EventSource> EventSource for Box<T> {
207 type Event = T::Event;
208 type Metadata = T::Metadata;
209 type Ret = T::Ret;
210 type Error = T::Error;
211
212 fn process_events<F>(
213 &mut self,
214 readiness: Readiness,
215 token: Token,
216 callback: F,
217 ) -> Result<PostAction, Self::Error>
218 where
219 F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
220 {
221 T::process_events(&mut **self, readiness, token, callback)
222 }
223
224 fn register(&mut self, poll: &mut Poll, token_factory: &mut TokenFactory) -> crate::Result<()> {
225 T::register(&mut **self, poll, token_factory)
226 }
227
228 fn reregister(
229 &mut self,
230 poll: &mut Poll,
231 token_factory: &mut TokenFactory,
232 ) -> crate::Result<()> {
233 T::reregister(&mut **self, poll, token_factory)
234 }
235
236 fn unregister(&mut self, poll: &mut Poll) -> crate::Result<()> {
237 T::unregister(&mut **self, poll)
238 }
239
240 const NEEDS_EXTRA_LIFECYCLE_EVENTS: bool = T::NEEDS_EXTRA_LIFECYCLE_EVENTS;
241
242 fn before_sleep(&mut self) -> crate::Result<Option<(Readiness, Token)>> {
243 T::before_sleep(&mut **self)
244 }
245
246 fn before_handle_events(&mut self, events: EventIterator) {
247 T::before_handle_events(&mut **self, events)
248 }
249}
250
251/// Blanket implementation for exclusive references to event sources.
252/// [`EventSource`] is not an object safe trait, so this does not include trait
253/// objects.
254impl<T: EventSource> EventSource for &mut T {
255 type Event = T::Event;
256 type Metadata = T::Metadata;
257 type Ret = T::Ret;
258 type Error = T::Error;
259
260 fn process_events<F>(
261 &mut self,
262 readiness: Readiness,
263 token: Token,
264 callback: F,
265 ) -> Result<PostAction, Self::Error>
266 where
267 F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
268 {
269 T::process_events(&mut **self, readiness, token, callback)
270 }
271
272 fn register(&mut self, poll: &mut Poll, token_factory: &mut TokenFactory) -> crate::Result<()> {
273 T::register(&mut **self, poll, token_factory)
274 }
275
276 fn reregister(
277 &mut self,
278 poll: &mut Poll,
279 token_factory: &mut TokenFactory,
280 ) -> crate::Result<()> {
281 T::reregister(&mut **self, poll, token_factory)
282 }
283
284 fn unregister(&mut self, poll: &mut Poll) -> crate::Result<()> {
285 T::unregister(&mut **self, poll)
286 }
287
288 const NEEDS_EXTRA_LIFECYCLE_EVENTS: bool = T::NEEDS_EXTRA_LIFECYCLE_EVENTS;
289
290 fn before_sleep(&mut self) -> crate::Result<Option<(Readiness, Token)>> {
291 T::before_sleep(&mut **self)
292 }
293
294 fn before_handle_events(&mut self, events: EventIterator) {
295 T::before_handle_events(&mut **self, events)
296 }
297}
298
299pub(crate) struct DispatcherInner<S, F> {
300 source: S,
301 callback: F,
302 needs_additional_lifecycle_events: bool,
303}
304
305impl<Data, S, F> EventDispatcher<Data> for RefCell<DispatcherInner<S, F>>
306where
307 S: EventSource,
308 F: FnMut(S::Event, &mut S::Metadata, &mut Data) -> S::Ret,
309{
310 fn process_events(
311 &self,
312 readiness: Readiness,
313 token: Token,
314 data: &mut Data,
315 ) -> crate::Result<PostAction> {
316 let mut disp = self.borrow_mut();
317 let DispatcherInner {
318 ref mut source,
319 ref mut callback,
320 ..
321 } = *disp;
322 trace!(
323 "[calloop] Processing events for source type {}",
324 std::any::type_name::<S>()
325 );
326 source
327 .process_events(readiness, token, |event, meta| callback(event, meta, data))
328 .map_err(|e| crate::Error::OtherError(e.into()))
329 }
330
331 fn register(
332 &self,
333 poll: &mut Poll,
334 additional_lifecycle_register: &mut AdditionalLifecycleEventsSet,
335 token_factory: &mut TokenFactory,
336 ) -> crate::Result<()> {
337 let mut this = self.borrow_mut();
338
339 if this.needs_additional_lifecycle_events {
340 additional_lifecycle_register.register(token_factory.registration_token());
341 }
342 this.source.register(poll, token_factory)
343 }
344
345 fn reregister(
346 &self,
347 poll: &mut Poll,
348 additional_lifecycle_register: &mut AdditionalLifecycleEventsSet,
349 token_factory: &mut TokenFactory,
350 ) -> crate::Result<bool> {
351 if let Ok(mut me) = self.try_borrow_mut() {
352 me.source.reregister(poll, token_factory)?;
353 if me.needs_additional_lifecycle_events {
354 additional_lifecycle_register.register(token_factory.registration_token());
355 }
356 Ok(true)
357 } else {
358 Ok(false)
359 }
360 }
361
362 fn unregister(
363 &self,
364 poll: &mut Poll,
365 additional_lifecycle_register: &mut AdditionalLifecycleEventsSet,
366 registration_token: RegistrationToken,
367 ) -> crate::Result<bool> {
368 if let Ok(mut me) = self.try_borrow_mut() {
369 me.source.unregister(poll)?;
370 if me.needs_additional_lifecycle_events {
371 additional_lifecycle_register.unregister(registration_token);
372 }
373 Ok(true)
374 } else {
375 Ok(false)
376 }
377 }
378
379 fn before_sleep(&self) -> crate::Result<Option<(Readiness, Token)>> {
380 let mut disp = self.borrow_mut();
381 let DispatcherInner { ref mut source, .. } = *disp;
382 source.before_sleep()
383 }
384
385 fn before_handle_events(&self, events: EventIterator<'_>) {
386 let mut disp = self.borrow_mut();
387 let DispatcherInner { ref mut source, .. } = *disp;
388 source.before_handle_events(events);
389 }
390}
391
392pub(crate) trait EventDispatcher<Data> {
393 fn process_events(
394 &self,
395 readiness: Readiness,
396 token: Token,
397 data: &mut Data,
398 ) -> crate::Result<PostAction>;
399
400 fn register(
401 &self,
402 poll: &mut Poll,
403 additional_lifecycle_register: &mut AdditionalLifecycleEventsSet,
404 token_factory: &mut TokenFactory,
405 ) -> crate::Result<()>;
406
407 fn reregister(
408 &self,
409 poll: &mut Poll,
410 additional_lifecycle_register: &mut AdditionalLifecycleEventsSet,
411 token_factory: &mut TokenFactory,
412 ) -> crate::Result<bool>;
413
414 fn unregister(
415 &self,
416 poll: &mut Poll,
417 additional_lifecycle_register: &mut AdditionalLifecycleEventsSet,
418 registration_token: RegistrationToken,
419 ) -> crate::Result<bool>;
420
421 fn before_sleep(&self) -> crate::Result<Option<(Readiness, Token)>>;
422 fn before_handle_events(&self, events: EventIterator<'_>);
423}
424
425#[derive(Default)]
426/// The list of events
427pub(crate) struct AdditionalLifecycleEventsSet {
428 /// The list of sources
429 pub(crate) values: Vec<RegistrationToken>,
430}
431
432impl AdditionalLifecycleEventsSet {
433 fn register(&mut self, token: RegistrationToken) {
434 self.values.push(token)
435 }
436
437 fn unregister(&mut self, token: RegistrationToken) {
438 self.values.retain(|it: &RegistrationToken| it != &token)
439 }
440}
441
442// An internal trait to erase the `F` type parameter of `DispatcherInner`
443trait ErasedDispatcher<'a, S, Data> {
444 fn as_source_ref(&self) -> Ref<S>;
445 fn as_source_mut(&self) -> RefMut<S>;
446 fn into_source_inner(self: Rc<Self>) -> S;
447 fn into_event_dispatcher(self: Rc<Self>) -> Rc<dyn EventDispatcher<Data> + 'a>;
448}
449
450impl<'a, S, Data, F> ErasedDispatcher<'a, S, Data> for RefCell<DispatcherInner<S, F>>
451where
452 S: EventSource + 'a,
453 F: FnMut(S::Event, &mut S::Metadata, &mut Data) -> S::Ret + 'a,
454{
455 fn as_source_ref(&self) -> Ref<S> {
456 Ref::map(self.borrow(), |inner: &DispatcherInner| &inner.source)
457 }
458
459 fn as_source_mut(&self) -> RefMut<S> {
460 RefMut::map(self.borrow_mut(), |inner: &mut DispatcherInner| &mut inner.source)
461 }
462
463 fn into_source_inner(self: Rc<Self>) -> S {
464 if let Ok(ref_cell: RefCell>) = Rc::try_unwrap(self) {
465 ref_cell.into_inner().source
466 } else {
467 panic!("Dispatcher is still registered");
468 }
469 }
470
471 fn into_event_dispatcher(self: Rc<Self>) -> Rc<dyn EventDispatcher<Data> + 'a>
472 where
473 S: 'a,
474 {
475 self as Rc<dyn EventDispatcher<Data> + 'a>
476 }
477}
478
479/// An event source with its callback.
480///
481/// The `Dispatcher` can be registered in an event loop.
482/// Use the `as_source_{ref,mut}` functions to interact with the event source.
483/// Use `into_source_inner` to get the event source back.
484pub struct Dispatcher<'a, S, Data>(Rc<dyn ErasedDispatcher<'a, S, Data> + 'a>);
485
486impl<'a, S, Data> std::fmt::Debug for Dispatcher<'a, S, Data> {
487 #[cfg_attr(feature = "nightly_coverage", coverage(off))]
488 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
489 f.write_str(data:"Dispatcher { ... }")
490 }
491}
492
493impl<'a, S, Data> Dispatcher<'a, S, Data>
494where
495 S: EventSource + 'a,
496{
497 /// Builds a dispatcher.
498 ///
499 /// The resulting `Dispatcher`
500 pub fn new<F>(source: S, callback: F) -> Self
501 where
502 F: FnMut(S::Event, &mut S::Metadata, &mut Data) -> S::Ret + 'a,
503 {
504 Dispatcher(Rc::new(RefCell::new(DispatcherInner {
505 source,
506 callback,
507 needs_additional_lifecycle_events: S::NEEDS_EXTRA_LIFECYCLE_EVENTS,
508 })))
509 }
510
511 /// Returns an immutable reference to the event source.
512 ///
513 /// # Panics
514 ///
515 /// Has the same semantics as `RefCell::borrow()`.
516 ///
517 /// The dispatcher being mutably borrowed while its events are dispatched,
518 /// this method will panic if invoked from within the associated dispatching closure.
519 pub fn as_source_ref(&self) -> Ref<S> {
520 self.0.as_source_ref()
521 }
522
523 /// Returns a mutable reference to the event source.
524 ///
525 /// # Panics
526 ///
527 /// Has the same semantics as `RefCell::borrow_mut()`.
528 ///
529 /// The dispatcher being mutably borrowed while its events are dispatched,
530 /// this method will panic if invoked from within the associated dispatching closure.
531 pub fn as_source_mut(&self) -> RefMut<S> {
532 self.0.as_source_mut()
533 }
534
535 /// Consumes the Dispatcher and returns the inner event source.
536 ///
537 /// # Panics
538 ///
539 /// Panics if the `Dispatcher` is still registered.
540 pub fn into_source_inner(self) -> S {
541 self.0.into_source_inner()
542 }
543
544 pub(crate) fn clone_as_event_dispatcher(&self) -> Rc<dyn EventDispatcher<Data> + 'a> {
545 Rc::clone(&self.0).into_event_dispatcher()
546 }
547}
548
549impl<'a, S, Data> Clone for Dispatcher<'a, S, Data> {
550 fn clone(&self) -> Dispatcher<'a, S, Data> {
551 Dispatcher(Rc::clone(&self.0))
552 }
553}
554
555/// An idle callback that was inserted in this loop
556///
557/// This handle allows you to cancel the callback. Dropping
558/// it will *not* cancel it.
559pub struct Idle<'i> {
560 pub(crate) callback: Rc<RefCell<dyn CancellableIdle + 'i>>,
561}
562
563impl<'i> std::fmt::Debug for Idle<'i> {
564 #[cfg_attr(feature = "nightly_coverage", coverage(off))]
565 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
566 f.write_str(data:"Idle { ... }")
567 }
568}
569
570impl<'i> Idle<'i> {
571 /// Cancel the idle callback if it was not already run
572 pub fn cancel(self) {
573 self.callback.borrow_mut().cancel();
574 }
575}
576
577pub(crate) trait CancellableIdle {
578 fn cancel(&mut self);
579}
580
581impl<F> CancellableIdle for Option<F> {
582 fn cancel(&mut self) {
583 self.take();
584 }
585}
586
587pub(crate) trait IdleDispatcher<Data> {
588 fn dispatch(&mut self, data: &mut Data);
589}
590
591impl<Data, F> IdleDispatcher<Data> for Option<F>
592where
593 F: FnMut(&mut Data),
594{
595 fn dispatch(&mut self, data: &mut Data) {
596 if let Some(callabck: &mut F) = self.as_mut() {
597 callabck(data);
598 }
599 }
600}
601
602#[cfg(test)]
603mod tests {
604 use std::time::Duration;
605
606 use crate::{ping::make_ping, EventLoop};
607
608 // Test event source boxing.
609 #[test]
610 fn test_boxed_source() {
611 let mut fired = false;
612
613 let (pinger, source) = make_ping().unwrap();
614 let boxed = Box::new(source);
615
616 let mut event_loop = EventLoop::try_new().unwrap();
617 let handle = event_loop.handle();
618
619 let token = handle
620 .insert_source(boxed, |_, _, fired| *fired = true)
621 .unwrap();
622
623 pinger.ping();
624
625 event_loop
626 .dispatch(Duration::new(0, 0), &mut fired)
627 .unwrap();
628
629 assert!(fired);
630 fired = false;
631
632 handle.update(&token).unwrap();
633
634 pinger.ping();
635
636 event_loop
637 .dispatch(Duration::new(0, 0), &mut fired)
638 .unwrap();
639
640 assert!(fired);
641 fired = false;
642
643 handle.remove(token);
644
645 event_loop
646 .dispatch(Duration::new(0, 0), &mut fired)
647 .unwrap();
648
649 assert!(!fired);
650 }
651
652 // Test event source trait methods via mut ref.
653 #[test]
654 fn test_mut_ref_source() {
655 let mut fired = false;
656
657 let (pinger, mut source) = make_ping().unwrap();
658 let source_ref = &mut source;
659
660 let mut event_loop = EventLoop::try_new().unwrap();
661 let handle = event_loop.handle();
662
663 let token = handle
664 .insert_source(source_ref, |_, _, fired| *fired = true)
665 .unwrap();
666
667 pinger.ping();
668
669 event_loop
670 .dispatch(Duration::new(0, 0), &mut fired)
671 .unwrap();
672
673 assert!(fired);
674 fired = false;
675
676 handle.update(&token).unwrap();
677
678 pinger.ping();
679
680 event_loop
681 .dispatch(Duration::new(0, 0), &mut fired)
682 .unwrap();
683
684 assert!(fired);
685 fired = false;
686
687 handle.remove(token);
688
689 event_loop
690 .dispatch(Duration::new(0, 0), &mut fired)
691 .unwrap();
692
693 assert!(!fired);
694 }
695
696 // Test PostAction combinations.
697 #[test]
698 fn post_action_combine() {
699 use super::PostAction::*;
700 assert_eq!(Continue | Continue, Continue);
701 assert_eq!(Continue | Reregister, Reregister);
702 assert_eq!(Continue | Disable, Reregister);
703 assert_eq!(Continue | Remove, Reregister);
704
705 assert_eq!(Reregister | Continue, Reregister);
706 assert_eq!(Reregister | Reregister, Reregister);
707 assert_eq!(Reregister | Disable, Reregister);
708 assert_eq!(Reregister | Remove, Reregister);
709
710 assert_eq!(Disable | Continue, Reregister);
711 assert_eq!(Disable | Reregister, Reregister);
712 assert_eq!(Disable | Disable, Disable);
713 assert_eq!(Disable | Remove, Reregister);
714
715 assert_eq!(Remove | Continue, Reregister);
716 assert_eq!(Remove | Reregister, Reregister);
717 assert_eq!(Remove | Disable, Reregister);
718 assert_eq!(Remove | Remove, Remove);
719 }
720
721 // Test PostAction self-assignment.
722 #[test]
723 fn post_action_combine_assign() {
724 use super::PostAction::*;
725
726 let mut action = Continue;
727 action |= Continue;
728 assert_eq!(action, Continue);
729
730 let mut action = Continue;
731 action |= Reregister;
732 assert_eq!(action, Reregister);
733
734 let mut action = Continue;
735 action |= Disable;
736 assert_eq!(action, Reregister);
737
738 let mut action = Continue;
739 action |= Remove;
740 assert_eq!(action, Reregister);
741
742 let mut action = Reregister;
743 action |= Continue;
744 assert_eq!(action, Reregister);
745
746 let mut action = Reregister;
747 action |= Reregister;
748 assert_eq!(action, Reregister);
749
750 let mut action = Reregister;
751 action |= Disable;
752 assert_eq!(action, Reregister);
753
754 let mut action = Reregister;
755 action |= Remove;
756 assert_eq!(action, Reregister);
757
758 let mut action = Disable;
759 action |= Continue;
760 assert_eq!(action, Reregister);
761
762 let mut action = Disable;
763 action |= Reregister;
764 assert_eq!(action, Reregister);
765
766 let mut action = Disable;
767 action |= Disable;
768 assert_eq!(action, Disable);
769
770 let mut action = Disable;
771 action |= Remove;
772 assert_eq!(action, Reregister);
773
774 let mut action = Remove;
775 action |= Continue;
776 assert_eq!(action, Reregister);
777
778 let mut action = Remove;
779 action |= Reregister;
780 assert_eq!(action, Reregister);
781
782 let mut action = Remove;
783 action |= Disable;
784 assert_eq!(action, Reregister);
785
786 let mut action = Remove;
787 action |= Remove;
788 assert_eq!(action, Remove);
789 }
790}
791