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}