diff options
author | Marcel Müller <m.mueller@ifm.com> | 2022-05-31 11:24:51 +0200 |
---|---|---|
committer | Marcel Müller <m.mueller@ifm.com> | 2022-05-31 11:24:51 +0200 |
commit | 3dc51be974294fafa60c9b73280b9be241277765 (patch) | |
tree | 5aa990ac60e6117d18659132991f6341c8fe1ecb | |
parent | 031832c6f22156694f0822265c5dd7b3b9683b9d (diff) | |
parent | 519ec731579a226aac53cec65c6b20cacfd3f586 (diff) |
Merge branch 'feature/add_type_uuids_to_messages' into feature/add_tedge_api_only
-rw-r--r-- | Cargo.lock | 27 | ||||
-rw-r--r-- | crates/core/tedge_api/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/core/tedge_api/README.md | 5 | ||||
-rw-r--r-- | crates/core/tedge_api/examples/heartbeat.rs | 11 | ||||
-rw-r--r-- | crates/core/tedge_api/examples/print_config.rs | 1 | ||||
-rw-r--r-- | crates/core/tedge_api/examples/universal_log.rs | 11 | ||||
-rw-r--r-- | crates/core/tedge_api/src/address.rs | 24 | ||||
-rw-r--r-- | crates/core/tedge_api/src/lib.rs | 7 | ||||
-rw-r--r-- | crates/core/tedge_api/src/message.rs | 64 | ||||
-rw-r--r-- | crates/core/tedge_api/src/plugin.rs | 80 | ||||
-rw-r--r-- | crates/core/tedge_api/tedge_config_derive/src/lib.rs | 2 |
11 files changed, 151 insertions, 82 deletions
@@ -2872,6 +2872,7 @@ dependencies = [ "tokio-util 0.7.0", "toml", "tracing", + "type-uuid", ] [[package]] @@ -3396,6 +3397,26 @@ dependencies = [ ] [[package]] +name = "type-uuid" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15043bca41f43205c9b0055d365a405d81b8e4a8ff99c36b263cf79ad1f4c051" +dependencies = [ + "type-uuid-derive", +] + +[[package]] +name = "type-uuid-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e090ee857961c746ecf7fb596022493ffaad54d189061df49f7a0cf17796dc1" +dependencies = [ + "quote 1.0.18", + "syn 1.0.93", + "uuid", +] + +[[package]] name = "typed-arena" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3490,6 +3511,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" + +[[package]] name = "value-bag" version = "1.0.0-alpha.8" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/crates/core/tedge_api/Cargo.toml b/crates/core/tedge_api/Cargo.toml index 5546ed2b..a4ff92ab 100644 --- a/crates/core/tedge_api/Cargo.toml +++ b/crates/core/tedge_api/Cargo.toml @@ -21,6 +21,7 @@ termimad = "0.20.1" nu-ansi-term = "0.45.1" tedge_config_derive = { version = "0.1.0", path = "tedge_config_derive" } tracing = "0.1" +type-uuid = "0.1.2" [dev-dependencies] pretty_assertions = "1.2.1" diff --git a/crates/core/tedge_api/README.md b/crates/core/tedge_api/README.md index 340faa23..8c59231a 100644 --- a/crates/core/tedge_api/README.md +++ b/crates/core/tedge_api/README.md @@ -85,7 +85,10 @@ others. For example: ```rust -#[derive(Debug)] +use tedge_api::{Message, TypeUuid}; + +#[derive(Debug, TypeUuid)] +#[uuid = "b60dd50c-ccef-4204-b370-18bbbb68d6e2"] struct Value(f64); impl Message for Value {} diff --git a/crates/core/tedge_api/examples/heartbeat.rs b/crates/core/tedge_api/examples/heartbeat.rs index 654c4311..8d64232a 100644 --- a/crates/core/tedge_api/examples/heartbeat.rs +++ b/crates/core/tedge_api/examples/heartbeat.rs @@ -4,23 +4,26 @@ use async_trait::async_trait; use futures::FutureExt; use tedge_api::{ address::ReplySenderFor, - message::MessageType, - plugin::{AcceptsReplies, BuiltPlugin, Handle, Message, PluginDeclaration, PluginExt}, + message::{AcceptsReplies, Message, MessageType}, + plugin::{BuiltPlugin, Handle, PluginDeclaration, PluginExt}, Address, CancellationToken, Plugin, PluginBuilder, PluginConfiguration, PluginDirectory, PluginError, }; use tokio::sync::RwLock; +use type_uuid::TypeUuid; +#[derive(Debug, TypeUuid)] +#[uuid = "94916be9-17ba-4bca-a3a0-408d33136fed"] /// A message that represents a heartbeat that gets sent to plugins -#[derive(Debug)] struct Heartbeat; impl Message for Heartbeat {} impl AcceptsReplies for Heartbeat { type Reply = HeartbeatStatus; } +#[derive(Debug, TypeUuid)] +#[uuid = "a6d03c65-51bf-4f89-b383-c67c9ed8533b"] /// The reply for a heartbeat -#[derive(Debug)] enum HeartbeatStatus { Alive, Degraded, diff --git a/crates/core/tedge_api/examples/print_config.rs b/crates/core/tedge_api/examples/print_config.rs index ba6e7a6b..8be855e0 100644 --- a/crates/core/tedge_api/examples/print_config.rs +++ b/crates/core/tedge_api/examples/print_config.rs @@ -1,3 +1,4 @@ +#![allow(dead_code, unused)] use std::collections::HashMap; use nu_ansi_term::Color; diff --git a/crates/core/tedge_api/examples/universal_log.rs b/crates/core/tedge_api/examples/universal_log.rs index 82ff3130..064ffa22 100644 --- a/crates/core/tedge_api/examples/universal_log.rs +++ b/crates/core/tedge_api/examples/universal_log.rs @@ -4,19 +4,22 @@ use async_trait::async_trait; use futures::FutureExt; use tedge_api::{ address::ReplySenderFor, - message::{AnyMessage, MessageType}, - plugin::{AnyMessages, BuiltPlugin, Handle, Message, PluginDeclaration, PluginExt}, + message::{AnyMessage, Message, MessageType}, + plugin::{AnyMessages, BuiltPlugin, Handle, PluginDeclaration, PluginExt}, Address, CancellationToken, Plugin, PluginBuilder, PluginConfiguration, PluginDirectory, PluginError, }; use tokio::sync::RwLock; +use type_uuid::TypeUuid; /// A message that represents a heartbeat that gets sent to plugins -#[derive(Debug)] +#[derive(Debug, TypeUuid)] +#[uuid = "1f807f7b-888f-4881-a1b5-16380e32f8c2"] struct Heartbeat; impl Message for Heartbeat {} -#[derive(Debug)] +#[derive(Debug, TypeUuid)] +#[uuid = "346e233f-c24a-47e0-a15b-3ec0d1e19019"] struct RandomData; impl Message for RandomData {} diff --git a/crates/core/tedge_api/src/address.rs b/crates/core/tedge_api/src/address.rs index 4f786ea5..4249ecfc 100644 --- a/crates/core/tedge_api/src/address.rs +++ b/crates/core/tedge_api/src/address.rs @@ -4,10 +4,7 @@ use futures::future::BoxFuture; use tokio::sync::RwLock; use tracing::{instrument, trace}; -use crate::{ - message::MessageType, - plugin::{AcceptsReplies, Message}, -}; +use crate::message::{AcceptsReplies, Message, MessageType}; #[doc(hidden)] pub type AnyMessageBox = Box<dyn Message>; @@ -363,13 +360,16 @@ pub trait Contains<M: Message> {} /// /// ```rust /// # use tedge_api::{Message, make_receiver_bundle}; +/// # use type_uuid::TypeUuid; /// -/// #[derive(Debug)] +/// #[derive(Debug, TypeUuid)] +/// #[uuid = "b4e62630-0404-4d39-b435-95d777029887"] /// struct IntMessage(u8); /// /// impl Message for IntMessage { } /// -/// #[derive(Debug)] +/// #[derive(Debug, TypeUuid)] +/// #[uuid = "92734ceb-7b65-499a-95cd-17164f1b3729"] /// struct StatusMessage(String); /// /// impl Message for StatusMessage { } @@ -406,15 +406,17 @@ mod tests { use static_assertions::{assert_impl_all, assert_not_impl_any}; use tokio::sync::RwLock; + use type_uuid::TypeUuid; use crate::{ address::{InnerMessageSender, ReplyReceiverFor, ReplySenderFor}, make_receiver_bundle, - plugin::{AcceptsReplies, Message}, + message::{AcceptsReplies, Message}, Address, }; - #[derive(Debug)] + #[derive(Debug, TypeUuid)] + #[uuid = "df2b8bb3-8c15-49bb-8d11-cc14d7f3b000"] struct Foo; impl Message for Foo {} @@ -422,12 +424,14 @@ mod tests { type Reply = Bar; } - #[derive(Debug)] + #[derive(Debug, TypeUuid)] + #[uuid = "953a243d-333a-4870-8297-272fff6262b5"] struct Bar; impl Message for Bar {} - #[derive(Debug)] + #[derive(Debug, TypeUuid)] + #[uuid = "fe98650c-b067-47f4-8fd8-2f3ed04fdc21"] struct Blub; impl Message for Blub {} diff --git a/crates/core/tedge_api/src/lib.rs b/crates/core/tedge_api/src/lib.rs index 5a9f77bb..f9716981 100644 --- a/crates/core/tedge_api/src/lib.rs +++ b/crates/core/tedge_api/src/lib.rs @@ -8,7 +8,7 @@ /// All the parts required to write a plugin pub mod plugin; -pub use plugin::{Message, Plugin, PluginBuilder, PluginConfiguration, PluginDirectory, PluginExt}; +pub use plugin::{Plugin, PluginBuilder, PluginConfiguration, PluginDirectory, PluginExt}; /// Generic representation of a configuration pub mod config; @@ -24,7 +24,7 @@ pub use error::PluginError; /// Predefined messages pub mod message; -pub use message::CoreMessages; +pub use message::{Message, CoreMessages}; /// Cancellation token used by `tedge_api` /// @@ -33,6 +33,9 @@ pub use tokio_util::sync::CancellationToken; /// Derive macro for self-describing configurations pub use tedge_config_derive::Config; +/// Derive macro for type uuids +pub use type_uuid::TypeUuid; + #[doc(hidden)] pub 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 3e4a6249..1e63a368 100644 --- a/crates/core/tedge_api/src/message.rs +++ b/crates/core/tedge_api/src/message.rs @@ -1,6 +1,35 @@ +use downcast_rs::{impl_downcast, DowncastSync}; use serde::Serialize; +use type_uuid::{TypeUuid, TypeUuidDynamic}; -use crate::{address::AnyMessageBox, plugin::Message}; +use crate::address::AnyMessageBox; + +/// An object that can be sent between [`Plugin`]s +/// +/// This trait is a marker trait for all types that can be used as messages which can be sent +/// between plugins in thin-edge. +pub trait Message: + Send + std::fmt::Debug + DynMessage + DowncastSync + TypeUuidDynamic + 'static +{ +} + +impl_downcast!(sync Message); + +/// A bag of messages making it easier to work with dynamic messages +pub trait DynMessage { + /// Get the type name of this message + fn type_name(&self) -> &'static str { + std::any::type_name::<Self>() + } +} + +impl<M: 'static> DynMessage for M {} + +/// Register that the [`Message`] can receive replies of kind `R`: [`Message`] +pub trait AcceptsReplies: Message { + /// The reply type that can be sent to implementing messages as replies + type Reply: Message; +} /// A message that can contain any other message /// @@ -8,7 +37,8 @@ use crate::{address::AnyMessageBox, plugin::Message}; /// otherwise. /// /// To construct it, you will need to have a message and call [`AnyMessage::from_message`] -#[derive(Debug)] +#[derive(Debug, TypeUuid)] +#[uuid = "e7e5c87b-2022-4687-8650-DEADBEEEEEEF"] pub struct AnyMessage(pub(crate) AnyMessageBox); impl std::ops::Deref for AnyMessage { @@ -50,11 +80,14 @@ pub struct MessageType { kind: MessageKind, } +#[derive(Clone, PartialEq, Debug)] +struct Uuid([u8; 16]); + #[derive(Debug, Clone, Serialize)] enum MessageKind { Wildcard, #[serde(skip)] - Typed(std::any::TypeId), + Typed(Uuid), } impl MessageType { @@ -79,26 +112,26 @@ impl MessageType { /// Get the [`MessageType`] for a `M`:[`Message`] #[must_use] - pub fn for_message<M: Message>() -> Self { - let id = std::any::TypeId::of::<M>(); + pub fn for_message<M: Message + TypeUuid>() -> Self { + let id = M::UUID; MessageType { name: std::any::type_name::<M>(), - kind: if id == std::any::TypeId::of::<AnyMessage>() { + kind: if id == AnyMessage::UUID { MessageKind::Wildcard } else { - MessageKind::Typed(id) + MessageKind::Typed(Uuid(id)) }, } } pub(crate) fn from_message(msg: &dyn Message) -> Self { - let id = msg.type_id(); + let id = msg.uuid(); MessageType { name: msg.type_name(), - kind: if id == std::any::TypeId::of::<AnyMessage>() { + kind: if id == AnyMessage::UUID { MessageKind::Wildcard } else { - MessageKind::Typed(id) + MessageKind::Typed(Uuid(id)) }, } } @@ -111,7 +144,8 @@ impl MessageType { } /// A message to tell the core to stop thin-edge -#[derive(Debug)] +#[derive(Debug, TypeUuid)] +#[uuid = "812b7235-671f-4722-b01a-333578b2a4ea"] pub struct StopCore; impl Message for StopCore {} @@ -120,16 +154,20 @@ crate::make_receiver_bundle!(pub struct CoreMessages(StopCore)); #[cfg(test)] mod tests { + use type_uuid::TypeUuid; + use crate::Message; use super::{AnyMessage, MessageType}; - #[derive(Debug)] + #[derive(Debug, TypeUuid)] + #[uuid = "0c2ed228-5ff0-4ba5-a0d3-3648f7eb6558"] struct Bar; impl Message for Bar {} - #[derive(Debug)] + #[derive(Debug, TypeUuid)] + #[uuid = "8c3beacb-327d-422d-a914-47006d521ba5"] struct Foo; impl Message for Foo {} diff --git a/crates/core/tedge_api/src/plugin.rs b/crates/core/tedge_api/src/plugin.rs index 431127cf..718dbf67 100644 --- a/crates/core/tedge_api/src/plugin.rs +++ b/crates/core/tedge_api/src/plugin.rs @@ -6,6 +6,7 @@ use futures::future::BoxFuture; use std::any::Any; +use type_uuid::TypeUuid; use downcast_rs::{impl_downcast, DowncastSync}; @@ -15,7 +16,7 @@ use crate::{ address::{InternalMessage, ReceiverBundle, ReplySenderFor}, config::ConfigDescription, error::{DirectoryError, PluginError}, - message::{CoreMessages, MessageType}, + message::{CoreMessages, Message, MessageType}, Address, }; @@ -96,10 +97,12 @@ pub trait PluginBuilder<PD: PluginDirectory>: Sync + Send + 'static { /// /// ```no_run /// # use tedge_api::{Plugin, plugin::BuiltPlugin, PluginError, PluginExt, PluginDirectory, PluginBuilder, PluginConfiguration}; + /// # use type_uuid::TypeUuid; /// - /// #[derive(Debug)] + /// #[derive(Debug, TypeUuid)] + /// #[uuid = "46f5d318-4158-4726-83dd-9b310cae3328"] /// struct MyMessage; - /// impl tedge_api::plugin::Message for MyMessage { } + /// impl tedge_api::Message for MyMessage { } /// /// struct MyPluginBuilder; /// struct MyPlugin; // + some impl Plugin for MyPlugin @@ -217,10 +220,12 @@ pub trait PluginBuilder<PD: PluginDirectory>: Sync + Send + 'static { /// # use tedge_api::PluginBuilder; /// # use tedge_api::PluginDirectory; /// # use tedge_api::PluginExt; + /// # use type_uuid::TypeUuid; /// - /// #[derive(Debug)] + /// #[derive(Debug, TypeUuid)] + /// #[uuid = "39046e3e-05ad-4b16-bbf1-8c2d2da5b668"] /// struct MyMessage; - /// impl tedge_api::plugin::Message for MyMessage { } + /// impl tedge_api::Message for MyMessage { } /// /// /// struct MyPluginBuilder; @@ -383,11 +388,13 @@ impl HandleTypes { /// # use tedge_api::address::ReplySenderFor; /// # use tedge_api::PluginError; /// # use tedge_api::PluginExt; + /// # use type_uuid::TypeUuid; /// - /// #[derive(Debug)] + /// #[derive(Debug, TypeUuid)] + /// #[uuid = "1276aa9c-5e04-4ab3-a987-61d89765ab33"] /// struct Heartbeat; /// - /// impl tedge_api::plugin::Message for Heartbeat { } + /// impl tedge_api::Message for Heartbeat { } /// /// struct HeartbeatPlugin; /// @@ -414,19 +421,19 @@ impl HandleTypes { /// # type HandledMessages = (Heartbeat,); /// # } /// - /// println!("{:#?}", HeartbeatPlugin::get_handled_types()); + /// println!("{:#x?}", HeartbeatPlugin::get_handled_types()); /// // This will print something akin to: /// // - /// // HandleTypes( - /// // [ - /// // ( - /// // "rust_out::main::_doctest_main_src_plugin_rs_102_0::Heartbeat", - /// // TypeId { - /// // t: 15512189350087767644, - /// // }, - /// // ), - /// // ], - /// // ) + /// // HandleTypes( + /// // [ + /// // MessageType { + /// // name: "rust_out::main::_doctest_main_src_plugin_rs_373_0::Heartbeat", + /// // kind: Typed( + /// // Uuid([ 0x12, 0x76, 0xaa, 0x9c, 0x5e, 0x4, 0x4a, 0xb3, 0xa9, 0x87, 0x61, 0xd8, 0x97, 0x65, 0xab, 0x33, ]) + /// // ), + /// // }, + /// // ], + /// // ) /// ``` pub fn declare_handlers_for<P: PluginDeclaration>() -> HandleTypes where @@ -436,30 +443,6 @@ impl HandleTypes { } } -/// An object that can be sent between [`Plugin`]s -/// -/// This trait is a marker trait for all types that can be used as messages which can be sent -/// between plugins in thin-edge. -pub trait Message: Send + std::fmt::Debug + DynMessage + DowncastSync + 'static {} - -impl_downcast!(sync Message); - -/// A bag of messages making it easier to work with dynamic messages -pub trait DynMessage { - /// Get the type name of this message - fn type_name(&self) -> &'static str { - std::any::type_name::<Self>() - } -} - -impl<M: 'static> DynMessage for M {} - -/// Register that the [`Message`] can receive replies of kind `R`: [`Message`] -pub trait AcceptsReplies: Message { - /// The reply type that can be sent to implementing messages as replies - type Reply: Message; -} - /// A bundle of messages /// /// This trait is implemented on types that represent a bundle of different types of messages. @@ -552,7 +535,7 @@ pub trait DoesHandle<M: MessageBundle> { macro_rules! impl_does_handle_tuple { () => {}; ($cur:ident $($rest:tt)*) => { - impl<$cur: Message, $($rest: Message,)* PLUG: Plugin + Handle<$cur> $(+ Handle<$rest>)*> DoesHandle<($cur, $($rest),*)> for PLUG { + impl<$cur: Message + TypeUuid, $($rest: Message + TypeUuid,)* PLUG: Plugin + Handle<$cur> $(+ Handle<$rest>)*> DoesHandle<($cur, $($rest),*)> for PLUG { fn into_built_plugin(self) -> BuiltPlugin { fn handle_message<'a, $cur: Message, $($rest: Message,)* PLUG: Plugin + Handle<$cur> $(+ Handle<$rest>)*>( plugin: &'a dyn Any, @@ -602,6 +585,8 @@ macro_rules! impl_does_handle_tuple { }; } +impl_does_handle_tuple!(M10 M9 M8 M7 M6 M5 M4 M3 M2 M1); + impl MessageBundle for () { fn get_ids() -> Vec<MessageType> { vec![] @@ -673,7 +658,7 @@ macro_rules! impl_msg_bundle_tuple { ($cur, impl_msg_bundle_tuple!(@rec_tuple $($rest)*)) }; ($cur:ident $($rest:tt)*) => { - impl<$cur: Message, $($rest: Message),*> MessageBundle for ($cur,$($rest),*) { + impl<$cur: Message + TypeUuid, $($rest: Message + TypeUuid),*> MessageBundle for ($cur,$($rest),*) { fn get_ids() -> Vec<MessageType> { vec![ MessageType::for_message::<$cur>(), @@ -687,20 +672,21 @@ 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); #[cfg(test)] mod tests { - use crate::{plugin::DynMessage, Message}; + use crate::{message::DynMessage, Message}; use super::{Plugin, PluginBuilder}; use static_assertions::assert_obj_safe; + use type_uuid::TypeUuid; // Object Safety assert_obj_safe!(PluginBuilder<()>); assert_obj_safe!(Plugin); - #[derive(Debug)] + #[derive(Debug, TypeUuid)] + #[uuid = "44d61fba-0055-4333-86bf-e96e06f7aea8"] struct Blub; impl Message for Blub {} diff --git a/crates/core/tedge_api/tedge_config_derive/src/lib.rs b/crates/core/tedge_api/tedge_config_derive/src/lib.rs index 5c34dbf2..b2a97098 100644 --- a/crates/core/tedge_api/tedge_config_derive/src/lib.rs +++ b/crates/core/tedge_api/tedge_config_derive/src/lib.rs @@ -1,6 +1,6 @@ use proc_macro::TokenStream as TS; use proc_macro2::TokenStream; -use proc_macro_error::{abort, emit_error, proc_macro_error, OptionExt, ResultExt}; +use proc_macro_error::{abort, proc_macro_error, OptionExt, ResultExt}; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{ parse_macro_input, Attribute, DeriveInput, Ident, Lit, LitStr, Meta, MetaNameValue, NestedMeta, |