From 4bcd48f5d4eb3db453ae94f2c10f8a4f44fb7283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Mon, 21 Mar 2022 09:35:25 +0100 Subject: Separate Message/ReceiverBundle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously they were mixed up, having them separate makes it clear that the bundle made by the `make_receiver_bundle` macro are only meant to be used for _receiving_ plugins. Signed-off-by: Marcel Müller --- crates/core/tedge_api/examples/heartbeat.rs | 4 +-- crates/core/tedge_api/src/address.rs | 49 ++++++++++++++++++++++++----- crates/core/tedge_api/src/lib.rs | 5 +++ crates/core/tedge_api/src/message.rs | 2 +- crates/core/tedge_api/src/plugin.rs | 38 ++++------------------ 5 files changed, 55 insertions(+), 43 deletions(-) diff --git a/crates/core/tedge_api/examples/heartbeat.rs b/crates/core/tedge_api/examples/heartbeat.rs index d2fc2f21..c882b99f 100644 --- a/crates/core/tedge_api/examples/heartbeat.rs +++ b/crates/core/tedge_api/examples/heartbeat.rs @@ -171,7 +171,7 @@ struct CriticalServiceBuilder; // declare a set of messages that the CriticalService can receive. // In this example, it can only receive a Heartbeat. -tedge_api::make_message_bundle!(struct HeartbeatMessages(Heartbeat)); +tedge_api::make_receiver_bundle!(struct HeartbeatMessages(Heartbeat)); #[async_trait] impl PluginBuilder for CriticalServiceBuilder { @@ -300,7 +300,7 @@ impl Communication { } impl PluginDirectory for Communication { - fn get_address_for( + fn get_address_for( &self, name: &str, ) -> Result, PluginError> { diff --git a/crates/core/tedge_api/src/address.rs b/crates/core/tedge_api/src/address.rs index fd23dd0a..d50ae596 100644 --- a/crates/core/tedge_api/src/address.rs +++ b/crates/core/tedge_api/src/address.rs @@ -1,6 +1,6 @@ use std::{marker::PhantomData, time::Duration}; -use crate::plugin::{Contains, Message, MessageBundle}; +use crate::plugin::Message; #[doc(hidden)] pub type AnySendBox = Box; @@ -26,19 +26,19 @@ pub type MessageReceiver = tokio::sync::mpsc::Receiver; /// well-defined type to a specific plugin. /// The `Address` instance can be used to send messages of several types, but each type has to be /// in `MB: MessageBundle`. -pub struct Address { +pub struct Address { _pd: PhantomData, sender: MessageSender, } -impl std::fmt::Debug for Address { +impl std::fmt::Debug for Address { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct(&format!("Address<{}>", std::any::type_name::())) .finish_non_exhaustive() } } -impl Clone for Address { +impl Clone for Address { fn clone(&self) -> Self { Self { _pd: PhantomData, @@ -47,7 +47,7 @@ impl Clone for Address { } } -impl Address { +impl Address { /// THIS IS NOT PART OF THE PUBLIC API, AND MAY CHANGE AT ANY TIME #[doc(hidden)] pub fn new(sender: MessageSender) -> Self { @@ -137,26 +137,59 @@ pub enum ReplyError { #[error("There was no response before timeout")] Timeout, #[error("Could not send reply")] - Unknown + Unknown, +} + +#[doc(hidden)] +pub trait ReceiverBundle { + fn get_ids() -> Vec<(&'static str, std::any::TypeId)>; +} + +#[doc(hidden)] +pub trait Contains {} + +/// Declare a set of messages to be a "MessageBundle" +/// +/// This macro can be used by a plugin author to declare a set of messages to be a `MessageBundle`. +#[macro_export] +macro_rules! make_receiver_bundle { + ($pu:vis struct $name:ident($($msg:ty),+)) => { + #[allow(missing_docs)] + #[derive(Debug)] + $pu struct $name; + + impl $crate::address::ReceiverBundle for $name { + #[allow(unused_parens)] + fn get_ids() -> Vec<(&'static str, std::any::TypeId)> { + vec![ + $((std::any::type_name::<$msg>(), std::any::TypeId::of::<$msg>())),+ + ] + } + } + + $(impl $crate::address::Contains<$msg> for $name {})+ + }; } #[cfg(test)] mod tests { - use crate::{make_message_bundle, plugin::Message, Address}; + use crate::{make_receiver_bundle, plugin::Message, Address}; + #[derive(Debug)] struct Foo; impl Message for Foo { type Reply = Bar; } + #[derive(Debug)] struct Bar; impl Message for Bar { type Reply = Bar; } - make_message_bundle!(struct FooBar(Foo, Bar)); + make_receiver_bundle!(struct FooBar(Foo, Bar)); #[allow(unreachable_code, dead_code, unused)] fn check_compile() { diff --git a/crates/core/tedge_api/src/lib.rs b/crates/core/tedge_api/src/lib.rs index 363967e0..d1495a0c 100644 --- a/crates/core/tedge_api/src/lib.rs +++ b/crates/core/tedge_api/src/lib.rs @@ -22,3 +22,8 @@ pub use error::PluginError; /// Predefined messages pub mod message; pub use message::CoreMessages; + +#[doc(hidden)] +mod _internal { + pub use futures::future::BoxFuture; +} diff --git a/crates/core/tedge_api/src/message.rs b/crates/core/tedge_api/src/message.rs index 5ff9f633..5b980d7b 100644 --- a/crates/core/tedge_api/src/message.rs +++ b/crates/core/tedge_api/src/message.rs @@ -16,4 +16,4 @@ impl Message for StopCore { type Reply = NoReply; } -crate::make_message_bundle!(pub struct CoreMessages(StopCore)); +crate::make_receiver_bundle!(pub struct CoreMessages(StopCore)); diff --git a/crates/core/tedge_api/src/plugin.rs b/crates/core/tedge_api/src/plugin.rs index f7bf70a1..3797f830 100644 --- a/crates/core/tedge_api/src/plugin.rs +++ b/crates/core/tedge_api/src/plugin.rs @@ -15,7 +15,7 @@ use downcast_rs::{impl_downcast, DowncastSync}; use async_trait::async_trait; use crate::{ - address::{InternalMessage, ReplySender}, + address::{InternalMessage, ReceiverBundle, ReplySender}, error::PluginError, message::CoreMessages, Address, @@ -41,7 +41,7 @@ pub trait PluginDirectory: Clone + Send + Sync { /// ## Also see /// /// - [`make_message_bundle`] On how to define your own named message bundle - fn get_address_for(&self, name: &str) -> Result, PluginError>; + fn get_address_for(&self, name: &str) -> Result, PluginError>; /// Request an `Address` to the core itself. It will only accept messages from the /// [`CoreMessages`] bundle. @@ -421,6 +421,10 @@ pub struct BuiltPlugin { } impl BuiltPlugin { + pub fn new(plugin: Box, handler: PluginHandlerFn) -> Self { + Self { plugin, handler } + } + /// Call the plugin with the given types. /// /// ## Panics @@ -450,9 +454,6 @@ pub trait DoesHandle { fn into_built_plugin(self) -> BuiltPlugin; } -#[doc(hidden)] -pub trait Contains {} - macro_rules! impl_does_handle_tuple { () => {}; ($cur:ident $($rest:tt)*) => { @@ -506,12 +507,6 @@ macro_rules! impl_does_handle_tuple { }; } -impl MessageBundle for M { - fn get_ids() -> Vec<(&'static str, TypeId)> { - vec![(std::any::type_name::(), TypeId::of::())] - } -} - impl MessageBundle for () { fn get_ids() -> Vec<(&'static str, TypeId)> { vec![] @@ -558,27 +553,6 @@ macro_rules! impl_msg_bundle_tuple { impl_msg_bundle_tuple!(M10 M9 M8 M7 M6 M5 M4 M3 M2 M1); impl_does_handle_tuple!(M10 M9 M8 M7 M6 M5 M4 M3 M2 M1); -/// Declare a set of messages to be a "MessageBundle" -/// -/// This macro can be used by a plugin author to declare a set of messages to be a `MessageBundle`. -#[macro_export] -macro_rules! make_message_bundle { - ($pu:vis struct $name:ident($($msg:ty),+)) => { - #[allow(missing_docs)] - #[derive(Debug)] - $pu struct $name; - - impl $crate::plugin::MessageBundle for $name { - #[allow(unused_parens)] - fn get_ids() -> Vec<(&'static str, std::any::TypeId)> { - <($($msg),+) as $crate::plugin::MessageBundle>::get_ids() - } - } - - $(impl $crate::plugin::Contains<$msg> for $name {})+ - }; -} - #[cfg(test)] mod tests { use super::{Plugin, PluginBuilder}; -- cgit v1.2.3