zenoh_flow_derive/lib.rs
1//
2// Copyright (c) 2021 - 2024 ZettaScale Technology
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7// which is available at https://www.apache.org/licenses/LICENSE-2.0.
8//
9// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10//
11// Contributors:
12// ZettaScale Zenoh Team, <zenoh@zettascale.tech>
13//
14
15//! This crate exposes three procedural macros (one for each type of node) to facilitate exposing the symbols required
16//! by Zenoh-Flow in order to dynamically load nodes.
17
18use proc_macro::TokenStream;
19use quote::quote;
20use syn::{parse_macro_input, DeriveInput};
21
22/// Expose the symbols Zenoh-Flow needs to instantiate and start a Source.
23///
24/// In addition to exposing a specific symbol that will not be mangled by the compiler, this macro records the version
25/// of the rust compiler used as well as the version of Zenoh-Flow. These additional information are here to (try) limit
26/// possible surprises due to the lack of stable ABI in Rust.
27///
28/// ## Example
29///
30/// ```
31/// # use async_trait::async_trait;
32/// # use zenoh_flow_nodes::prelude::*;
33/// #[export_source]
34/// pub struct MySource {
35/// // Your logic goes here.
36/// }
37/// # #[async_trait]
38/// # impl Source for MySource{
39/// # async fn new(
40/// # context: Context,
41/// # configuration: Configuration,
42/// # outputs: Outputs,
43/// # ) -> Result<Self> {
44/// # todo!()
45/// # }
46/// # }
47///
48/// # #[async_trait]
49/// # impl Node for MySource {
50/// # async fn iteration(&self) -> Result<()> {
51/// # todo!()
52/// # }
53/// # }
54/// ```
55#[proc_macro_attribute]
56pub fn export_source(_: TokenStream, input: TokenStream) -> TokenStream {
57 let ast = parse_macro_input!(input as DeriveInput);
58 let ident = &ast.ident;
59
60 let gen = quote! {
61
62 #ast
63
64 #[doc(hidden)]
65 #[no_mangle]
66 pub static _zf_export_source: zenoh_flow_nodes::NodeDeclaration<
67 zenoh_flow_nodes::SourceFn,
68 > = zenoh_flow_nodes::NodeDeclaration::<
69 zenoh_flow_nodes::SourceFn,
70 > {
71 rustc_version: zenoh_flow_nodes::RUSTC_VERSION,
72 core_version: zenoh_flow_nodes::CORE_VERSION,
73 constructor: |context: zenoh_flow_nodes::prelude::Context,
74 configuration: zenoh_flow_nodes::prelude::Configuration,
75 outputs: zenoh_flow_nodes::prelude::Outputs| {
76 std::boxed::Box::pin(async {
77 let node = <#ident>::new(context, configuration, outputs).await?;
78 Ok(std::sync::Arc::new(node) as std::sync::Arc<dyn zenoh_flow_nodes::prelude::Node>)
79 })
80 },
81 };
82 };
83 gen.into()
84}
85
86/// Expose the symbols Zenoh-Flow needs to instantiate and start a Sink.
87///
88/// In addition to exposing a specific symbol that will not be mangled by the compiler, this macro records the version
89/// of the rust compiler used as well as the version of Zenoh-Flow. These additional information are here to (try) limit
90/// possible surprises due to the lack of stable ABI in Rust.
91///
92/// ## Example
93///
94/// ```
95/// # use async_trait::async_trait;
96/// # use zenoh_flow_nodes::prelude::*;
97/// #[export_sink]
98/// pub struct MySink {
99/// // Your logic goes here.
100/// }
101/// # #[async_trait]
102/// # impl Sink for MySink {
103/// # async fn new(
104/// # context: Context,
105/// # configuration: Configuration,
106/// # inputs: Inputs,
107/// # ) -> Result<Self> {
108/// # todo!()
109/// # }
110/// # }
111///
112/// # #[async_trait]
113/// # impl Node for MySink {
114/// # async fn iteration(&self) -> Result<()> {
115/// # todo!()
116/// # }
117/// # }
118/// ```
119#[proc_macro_attribute]
120pub fn export_sink(_: TokenStream, input: TokenStream) -> TokenStream {
121 let ast = parse_macro_input!(input as DeriveInput);
122 let ident = &ast.ident;
123
124 let sink = quote! {#ast};
125
126 let constructor = quote! {
127
128 #[doc(hidden)]
129 #[no_mangle]
130 pub static _zf_export_sink: zenoh_flow_nodes::NodeDeclaration<
131 zenoh_flow_nodes::SinkFn,
132 > = zenoh_flow_nodes::NodeDeclaration::<
133 zenoh_flow_nodes::SinkFn,
134 > {
135 rustc_version: zenoh_flow_nodes::RUSTC_VERSION,
136 core_version: zenoh_flow_nodes::CORE_VERSION,
137 constructor: |context: zenoh_flow_nodes::prelude::Context,
138 configuration: zenoh_flow_nodes::prelude::Configuration,
139 mut inputs: zenoh_flow_nodes::prelude::Inputs| {
140 std::boxed::Box::pin(async {
141 let node = <#ident>::new(context, configuration, inputs).await?;
142 Ok(std::sync::Arc::new(node) as std::sync::Arc<dyn zenoh_flow_nodes::prelude::Node>)
143 })
144 },
145 };
146 };
147
148 let gen = quote! {
149 #sink
150 #constructor
151
152 };
153 gen.into()
154}
155
156/// Expose the symbols Zenoh-Flow needs to instantiate and start a Operator.
157///
158/// In addition to exposing a specific symbol that will not be mangled by the compiler, this macro records the version
159/// of the rust compiler used as well as the version of Zenoh-Flow. These additional information are here to (try) limit
160/// possible surprises due to the lack of stable ABI in Rust.
161///
162/// ## Example
163///
164/// ```
165/// # use async_trait::async_trait;
166/// # use zenoh_flow_nodes::prelude::*;
167/// #[export_operator]
168/// pub struct MyOperator {
169/// // Your logic code goes here.
170/// }
171/// # #[async_trait]
172/// # impl Operator for MyOperator {
173/// # async fn new(
174/// # context: Context,
175/// # configuration: Configuration,
176/// # inputs: Inputs,
177/// # outputs: Outputs,
178/// # ) -> Result<Self>
179/// # where
180/// # Self: Sized {
181/// # todo!()
182/// # }
183/// # }
184///
185/// # #[async_trait]
186/// # impl Node for MyOperator {
187/// # async fn iteration(&self) -> Result<()> {
188/// # todo!()
189/// # }
190/// # }
191/// ```
192#[proc_macro_attribute]
193pub fn export_operator(_: TokenStream, input: TokenStream) -> TokenStream {
194 let ast = parse_macro_input!(input as DeriveInput);
195 let ident = &ast.ident;
196
197 let gen = quote! {
198
199 #ast
200
201 #[doc(hidden)]
202 #[no_mangle]
203 pub static _zf_export_operator: zenoh_flow_nodes::NodeDeclaration<
204 zenoh_flow_nodes::OperatorFn,
205 > = zenoh_flow_nodes::NodeDeclaration::<
206 zenoh_flow_nodes::OperatorFn,
207 > {
208 rustc_version: zenoh_flow_nodes::RUSTC_VERSION,
209 core_version: zenoh_flow_nodes::CORE_VERSION,
210 constructor: |context: zenoh_flow_nodes::prelude::Context,
211 configuration: zenoh_flow_nodes::prelude::Configuration,
212 mut inputs: zenoh_flow_nodes::prelude::Inputs,
213 mut outputs: zenoh_flow_nodes::prelude::Outputs| {
214 std::boxed::Box::pin(async {
215 let node = <#ident>::new(context, configuration, inputs, outputs).await?;
216 Ok(std::sync::Arc::new(node) as std::sync::Arc<dyn zenoh_flow_nodes::prelude::Node>)
217 })
218 },
219 };
220 };
221 gen.into()
222}