From 7226b924d6945a06dc7d0610f94e419f322f5c4c Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sun, 8 Sep 2024 10:31:09 +0200 Subject: [PATCH] scaffoldig macro, sessiondeclaration wrapped --- commons/zenoh-macros/src/lib.rs | 83 ++++++++++++++++++- plugins/zenoh-plugin-example/src/lib.rs | 1 - .../zenoh-plugin-rest/examples/z_serve_sse.rs | 1 - plugins/zenoh-plugin-rest/src/lib.rs | 2 +- .../src/replica/storage.rs | 2 +- zenoh/src/api/info.rs | 2 +- zenoh/src/api/publisher.rs | 2 +- zenoh/src/api/queryable.rs | 2 +- zenoh/src/api/session.rs | 5 +- zenoh/src/api/subscriber.rs | 4 +- zenoh/src/lib.rs | 2 +- zenoh/src/prelude.rs | 2 +- zenoh/tests/events.rs | 1 - 13 files changed, 95 insertions(+), 14 deletions(-) diff --git a/commons/zenoh-macros/src/lib.rs b/commons/zenoh-macros/src/lib.rs index 003525daa9..4ca1fd916e 100644 --- a/commons/zenoh-macros/src/lib.rs +++ b/commons/zenoh-macros/src/lib.rs @@ -17,9 +17,13 @@ //! This crate is intended for Zenoh's internal use. //! //! [Click here for Zenoh's documentation](../zenoh/index.html) +use std::process::Output; + 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, Lifetime, LitStr, TraitItem, +}; use zenoh_keyexpr::{ format::{ macro_support::{self, SegmentBuilder}, @@ -522,3 +526,80 @@ pub fn register_param(input: proc_macro::TokenStream) -> proc_macro::TokenStream .unwrap_or_else(syn::Error::into_compile_error) .into() } + +/// +/// Implements macro `#[scaffolding]` which precedes +/// `impl Trait for Struct { ... }`` +/// +/// This macro adds section `impl Struct` with the same funcations as in `impl Trait` +/// making methods with the same name as in trait be avaliable from struct directly, +/// without importing the trait. +/// +#[proc_macro_attribute] +pub fn scaffolding(_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_name_str = method_name.to_string(); + // let method_name_ident = syn::Ident::new(&method_name_str, method_name.span()); + 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, }); + } + } + }; + // call corresponding trait method from struct method + struct_methods.extend(quote! { + 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 + } + }; + + // let struct_methods_output = if let Some(struct_lifetime) = struct_lifetime { + // quote! { + // impl<#struct_lifetime> #struct_path { + // #struct_methods + // } + // } + // } else { + // quote! { + // impl #struct_path { + // #struct_methods + // } + // } + // }; + + (quote! { + #input + #struct_methods_output + }).into() +} diff --git a/plugins/zenoh-plugin-example/src/lib.rs b/plugins/zenoh-plugin-example/src/lib.rs index b7c494946d..086e23aaa8 100644 --- a/plugins/zenoh-plugin-example/src/lib.rs +++ b/plugins/zenoh-plugin-example/src/lib.rs @@ -36,7 +36,6 @@ use zenoh::{ key_expr::{keyexpr, KeyExpr}, prelude::ZResult, sample::Sample, - session::SessionDeclarations, }; use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginControl}; diff --git a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs index aefdfd4f86..fbd0269498 100644 --- a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs +++ b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs @@ -18,7 +18,6 @@ use zenoh::{ config::Config, key_expr::keyexpr, qos::{CongestionControl, QoSBuilderTrait}, - 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..90ad21ffdb 100644 --- a/plugins/zenoh-plugin-rest/src/lib.rs +++ b/plugins/zenoh-plugin-rest/src/lib.rs @@ -47,7 +47,7 @@ use zenoh::{ prelude::*, query::{Parameters, QueryConsolidation, Reply, Selector, ZenohParameters}, sample::{Sample, SampleKind}, - session::{Session, SessionDeclarations}, + session::{Session}, }; use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginControl}; diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index d2147b137c..5b3d88a080 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -36,7 +36,7 @@ use zenoh::{ }, query::{ConsolidationMode, QueryTarget}, sample::{Sample, SampleBuilder, SampleKind, TimestampBuilderTrait}, - session::{Session, SessionDeclarations}, + session::{Session}, time::{Timestamp, NTP64}, }; use zenoh_backend_traits::{ diff --git a/zenoh/src/api/info.rs b/zenoh/src/api/info.rs index 32bed0eb53..8275128099 100644 --- a/zenoh/src/api/info.rs +++ b/zenoh/src/api/info.rs @@ -159,7 +159,7 @@ impl<'a> IntoFuture for PeersZenohIdBuilder<'a> { } } -/// Struct returned by [`Session::info()`](crate::session::SessionDeclarations::info) which allows +/// Struct returned by [`Session::info()`](crate::session::Session::info) which allows /// to access information about the current zenoh [`Session`](crate::Session). /// /// # Examples diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index 2b13ee32af..4e32d075c8 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -1129,7 +1129,7 @@ mod tests { use zenoh_config::Config; use zenoh_core::Wait; - use crate::api::{sample::SampleKind, session::SessionDeclarations}; + use crate::api::{sample::SampleKind}; #[cfg(feature = "internal")] #[test] diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index 61ae0093ea..d7d3b0811f 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -774,7 +774,7 @@ impl<'a, 'b, Handler> QueryableBuilder<'a, 'b, Handler> { /// A queryable that provides data through a [`Handler`](crate::handlers::IntoHandler). /// /// Queryables can be created from a zenoh [`Session`](crate::Session) -/// with the [`declare_queryable`](crate::session::SessionDeclarations::declare_queryable) function +/// with the [`declare_queryable`](crate::session::Session::declare_queryable) function /// and the [`with`](QueryableBuilder::with) function /// of the resulting builder. /// diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index 26704d378a..84dbd88147 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -30,6 +30,7 @@ use zenoh_buffers::ZBuf; use zenoh_collections::SingleOrVec; use zenoh_config::{unwrap_or_default, wrappers::ZenohId, Config, Notifier}; use zenoh_core::{zconfigurable, zread, Resolvable, Resolve, ResolveClosure, ResolveFuture, Wait}; +use zenoh_macros::scaffolding; #[cfg(feature = "unstable")] use zenoh_protocol::network::{ declare::{DeclareToken, SubscriberId, TokenId, UndeclareToken}, @@ -365,6 +366,7 @@ pub enum SessionRef<'a> { Shared(Arc), } +#[scaffolding] impl<'s, 'a> SessionDeclarations<'s, 'a> for SessionRef<'a> { fn declare_subscriber<'b, TryIntoKeyExpr>( &'s self, @@ -706,8 +708,9 @@ impl Session { } } +#[scaffolding] impl<'a> SessionDeclarations<'a, 'a> for Session { - fn info(&self) -> SessionInfo { + fn info(&'a self) -> SessionInfo<'a> { SessionRef::Borrow(self).info() } fn declare_subscriber<'b, TryIntoKeyExpr>( diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index 0e82a20331..510f36a9fb 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -55,7 +55,7 @@ impl fmt::Debug for SubscriberState { /// A subscriber that provides data through a callback. /// /// CallbackSubscribers can be created from a zenoh [`Session`](crate::Session) -/// with the [`declare_subscriber`](crate::SessionDeclarations::declare_subscriber) function +/// with the [`declare_subscriber`](crate::session::Session::declare_subscriber) function /// and the [`callback`](SubscriberBuilder::callback) function /// of the resulting builder. /// @@ -421,7 +421,7 @@ where /// A subscriber that provides data through a [`Handler`](crate::handlers::IntoHandler). /// /// Subscribers can be created from a zenoh [`Session`](crate::Session) -/// with the [`declare_subscriber`](crate::session::SessionDeclarations::declare_subscriber) function +/// with the [`declare_subscriber`](crate::session::Session::declare_subscriber) function /// and the [`with`](SubscriberBuilder::with) function /// of the resulting builder. /// diff --git a/zenoh/src/lib.rs b/zenoh/src/lib.rs index 12adb11678..2c49b86ef6 100644 --- a/zenoh/src/lib.rs +++ b/zenoh/src/lib.rs @@ -197,7 +197,7 @@ pub mod session { builders::publisher::{SessionDeleteBuilder, SessionPutBuilder}, info::{PeersZenohIdBuilder, RoutersZenohIdBuilder, SessionInfo, ZenohIdBuilder}, query::SessionGetBuilder, - session::{open, OpenBuilder, Session, SessionDeclarations, SessionRef, Undeclarable}, + session::{open, OpenBuilder, Session, SessionRef, Undeclarable}, }; } diff --git a/zenoh/src/prelude.rs b/zenoh/src/prelude.rs index 373d56c65a..067c11031c 100644 --- a/zenoh/src/prelude.rs +++ b/zenoh/src/prelude.rs @@ -34,7 +34,7 @@ mod _prelude { builders::sample::{ EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, }, - session::{SessionDeclarations, Undeclarable}, + session::{Undeclarable}, }, config::ValidatedMap, Error as ZError, Resolvable, Resolve, Result as ZResult, diff --git a/zenoh/tests/events.rs b/zenoh/tests/events.rs index 11a6e18b53..e3a4d61656 100644 --- a/zenoh/tests/events.rs +++ b/zenoh/tests/events.rs @@ -52,7 +52,6 @@ async fn close_session(session: Session) { #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn zenoh_events() { - use zenoh::prelude::SessionDeclarations; let session = open_session(&["tcp/127.0.0.1:18447"], &[]).await; let zid = session.zid(); let sub1 =