netstack3_base/
event.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Types and traits defining events emitted from core to bindings.
6
7/// A context for emitting events.
8///
9/// `EventContext` encodes the common pattern for emitting atomic events of type
10/// `T` from core. An implementation of `EventContext` must guarantee that
11/// events are processed in the order they are emitted.
12pub trait EventContext<T> {
13    /// Handles `event`.
14    fn on_event(&mut self, event: T);
15}
16
17/// An event context implemented by core contexts to wrap event types that are
18/// not exposed to bindings.
19pub trait CoreEventContext<T> {
20    /// The outer event type.
21    type OuterEvent;
22    /// Converts the event to the outer event type.
23    fn convert_event(event: T) -> Self::OuterEvent;
24
25    /// A helper to emit an `event` through a bindings context that implements
26    /// [`EventContext`] on the [`OuterEvent`].
27    fn on_event<BC: EventContext<Self::OuterEvent>>(bindings_ctx: &mut BC, event: T) {
28        bindings_ctx.on_event(Self::convert_event(event))
29    }
30}
31
32#[cfg(any(test, feature = "testutils"))]
33pub(crate) mod testutil {
34    use super::*;
35
36    use alloc::vec::Vec;
37    use core::fmt::Debug;
38
39    /// A fake [`EventContext`].
40    pub struct FakeEventCtx<E: Debug> {
41        events: Vec<E>,
42        must_watch_all_events: bool,
43    }
44
45    impl<E: Debug> EventContext<E> for FakeEventCtx<E> {
46        fn on_event(&mut self, event: E) {
47            self.events.push(event)
48        }
49    }
50
51    impl<E: Debug> Drop for FakeEventCtx<E> {
52        fn drop(&mut self) {
53            if self.must_watch_all_events {
54                assert!(
55                    self.events.is_empty(),
56                    "dropped context with unacknowledged events: {:?}",
57                    self.events
58                );
59            }
60        }
61    }
62
63    impl<E: Debug> Default for FakeEventCtx<E> {
64        fn default() -> Self {
65            Self { events: Default::default(), must_watch_all_events: false }
66        }
67    }
68
69    impl<E: Debug> FakeEventCtx<E> {
70        /// Takes all events from the context.
71        ///
72        /// After calling `take`, the caller opts into event watching and must
73        /// acknowledge all events before fropping the `FakeEventCtx`.
74        pub fn take(&mut self) -> Vec<E> {
75            // Any client that calls `take()` is opting into watching events
76            // and must watch them all.
77            self.must_watch_all_events = true;
78            core::mem::take(&mut self.events)
79        }
80    }
81}