diff --git a/commons/zenoh-macros/src/lib.rs b/commons/zenoh-macros/src/lib.rs index 003525daa9..f3533a6aea 100644 --- a/commons/zenoh-macros/src/lib.rs +++ b/commons/zenoh-macros/src/lib.rs @@ -19,7 +19,7 @@ //! [Click here for Zenoh's documentation](../zenoh/index.html) use proc_macro::TokenStream; use quote::{quote, ToTokens}; -use syn::{parse_macro_input, parse_quote, Attribute, Error, Item, LitStr, TraitItem}; +use syn::{parse_macro_input, parse_quote, Attribute, Error, Item, ItemImpl, LitStr, TraitItem}; use zenoh_keyexpr::{ format::{ macro_support::{self, SegmentBuilder}, @@ -522,3 +522,81 @@ pub fn register_param(input: proc_macro::TokenStream) -> proc_macro::TokenStream .unwrap_or_else(syn::Error::into_compile_error) .into() } + +/// Macro `#[internal_trait]` should precede +/// `impl Trait for Struct { ... }` +/// +/// This macro wraps the implementations of "internal" tratis. +/// +/// These traits are used to group set of functions which should be implemented +/// together and with the same portotyoe. E.g. `QoSBuilderTrait` provides set of +/// setters (`congestion_control`, `priority`, `express`) and we should not +/// forget to implement all these setters for each entity which supports +/// QoS functionality. +/// +/// The traits mechanism is a good way to group functions. But additional traits +/// adds extra burden to end user who have to import it every time. +/// +/// The macro `internal_trait` solves this problem by adding +/// methods with same names as in trait to structure implementation itself, +/// making them available to user without additional trait import. +/// +#[proc_macro_attribute] +pub fn internal_trait(_attr: TokenStream, item: TokenStream) -> TokenStream { + let input = parse_macro_input!(item as ItemImpl); + let trait_path = &input.trait_.as_ref().unwrap().1; + let struct_path = &input.self_ty; + let generics = &input.generics; + // let struct_lifetime = get_type_path_lifetime(struct_path); + + let mut struct_methods = quote! {}; + for item_fn in input.items.iter() { + if let syn::ImplItem::Fn(method) = item_fn { + let method_name = &method.sig.ident; + let method_generic_params = &method.sig.generics.params; + let method_generic_params = if method_generic_params.is_empty() { + quote! {} + } else { + quote! {<#method_generic_params>} + }; + let method_args = &method.sig.inputs; + let method_output = &method.sig.output; + let where_clause = &method.sig.generics.where_clause; + let mut method_call_args = quote! {}; + for arg in method_args.iter() { + match arg { + syn::FnArg::Receiver(_) => { + method_call_args.extend(quote! { self, }); + } + syn::FnArg::Typed(pat_type) => { + let pat = &pat_type.pat; + method_call_args.extend(quote! { #pat, }); + } + } + } + let mut attributes = quote! {}; + for attr in &method.attrs { + attributes.extend(quote! { + #attr + }); + } + // call corresponding trait method from struct method + struct_methods.extend(quote! { + #attributes + pub fn #method_name #method_generic_params (#method_args) #method_output #where_clause { + <#struct_path as #trait_path>::#method_name(#method_call_args) + } + }); + } + } + let struct_methods_output = quote! { + impl #generics #struct_path { + #struct_methods + } + }; + (quote! { + #input + #struct_methods_output + }) + .into() +} diff --git a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs index aefdfd4f86..161e647457 100644 --- a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs +++ b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs @@ -15,10 +15,7 @@ use std::time::Duration; use clap::{arg, Command}; use zenoh::{ - config::Config, - key_expr::keyexpr, - qos::{CongestionControl, QoSBuilderTrait}, - session::SessionDeclarations, + config::Config, key_expr::keyexpr, qos::CongestionControl, session::SessionDeclarations, }; const HTML: &str = r#" diff --git a/plugins/zenoh-plugin-rest/src/lib.rs b/plugins/zenoh-plugin-rest/src/lib.rs index eb65a991d6..7ed44ebe2f 100644 --- a/plugins/zenoh-plugin-rest/src/lib.rs +++ b/plugins/zenoh-plugin-rest/src/lib.rs @@ -53,7 +53,7 @@ use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginCont mod config; pub use config::Config; -use zenoh::{bytes::EncodingBuilderTrait, query::ReplyError}; +use zenoh::query::ReplyError; const GIT_VERSION: &str = git_version::git_version!(prefix = "v", cargo_prefix = "v"); lazy_static::lazy_static! { diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index 952a72f499..cf38fe4728 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -24,7 +24,6 @@ use tokio::sync::RwLock; use zenoh::{ internal::Value, key_expr::{KeyExpr, OwnedKeyExpr}, - prelude::*, query::Selector, sample::{Sample, SampleBuilder}, time::Timestamp, diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index d2147b137c..7352ccdeb7 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -23,7 +23,6 @@ use flume::{Receiver, Sender}; use futures::select; use tokio::sync::{Mutex, RwLock}; use zenoh::{ - bytes::EncodingBuilderTrait, internal::{ buffers::{SplitBuffer, ZBuf}, zenoh_home, Timed, TimedEvent, Timer, Value, @@ -35,7 +34,7 @@ use zenoh::{ KeyExpr, OwnedKeyExpr, }, query::{ConsolidationMode, QueryTarget}, - sample::{Sample, SampleBuilder, SampleKind, TimestampBuilderTrait}, + sample::{Sample, SampleBuilder, SampleKind}, session::{Session, SessionDeclarations}, time::{Timestamp, NTP64}, }; diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index 224abfde87..e3ab70c1c6 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -27,7 +27,7 @@ use zenoh::{ prelude::Wait, pubsub::{Reliability, Subscriber}, query::{QueryConsolidation, QueryTarget, ReplyKeyExpr, Selector}, - sample::{Locality, Sample, SampleBuilder, TimestampBuilderTrait}, + sample::{Locality, Sample, SampleBuilder}, session::{SessionDeclarations, SessionRef}, time::Timestamp, Error, Resolvable, Resolve, Result as ZResult, diff --git a/zenoh/src/api/builders/publisher.rs b/zenoh/src/api/builders/publisher.rs index 8a6961ac55..d361272f66 100644 --- a/zenoh/src/api/builders/publisher.rs +++ b/zenoh/src/api/builders/publisher.rs @@ -18,12 +18,11 @@ use zenoh_core::{Resolvable, Result as ZResult, Wait}; use zenoh_protocol::core::Reliability; use zenoh_protocol::{core::CongestionControl, network::Mapping}; +use super::sample::TimestampBuilderTrait; #[cfg(feature = "unstable")] use crate::api::sample::SourceInfo; use crate::api::{ - builders::sample::{ - EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, - }, + builders::sample::{EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait}, bytes::{OptionZBytes, ZBytes}, encoding::Encoding, key_expr::KeyExpr, @@ -80,6 +79,7 @@ pub struct PublicationBuilder
{
pub(crate) attachment: Option EncodingBuilderTrait for PublicationBuilder {
fn encoding EncodingBuilderTrait for PublicationBuilder {
}
}
+#[zenoh_macros::internal_trait]
impl SampleBuilderTrait for PublicationBuilder {
#[cfg(feature = "unstable")]
fn source_info(self, source_info: SourceInfo) -> Self {
@@ -164,6 +167,7 @@ impl SampleBuilderTrait for PublicationBuilder {
}
}
+#[zenoh_macros::internal_trait]
impl TimestampBuilderTrait for PublicationBuilder {
fn timestamp