calloop/sources/
mod.rs

1use std::{
2    cell::{Ref, RefCell, RefMut},
3    ops::{BitOr, BitOrAssign},
4    rc::Rc,
5};
6
7use tracing::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            "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| 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| &inner.source)
457    }
458
459    fn as_source_mut(&self) -> RefMut<S> {
460        RefMut::map(self.borrow_mut(), |inner| &mut inner.source)
461    }
462
463    fn into_source_inner(self: Rc<Self>) -> S {
464        if let Ok(ref_cell) = 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("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("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) = 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}