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