tugraph_plugin_util_proc_macros/
mod.rs

1// Copyright 2023 antkiller
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use proc_macro::{TokenStream, TokenTree::Ident};
16use quote::quote;
17
18/// A helper attribute macro brings easy life to write tugraph rust procedure
19#[proc_macro_attribute]
20pub fn tugraph_plugin(_attr: TokenStream, input: TokenStream) -> TokenStream {
21    // skip the first identifier(keyword) `fn`
22    // the second identifier is name of function.
23    let func_name = input
24        .clone()
25        .into_iter()
26        .find_map(|tt| match tt {
27            Ident(ref name) if name.to_string() != "fn" && name.to_string() != "pub" => Some(tt),
28            _ => None,
29        })
30        .unwrap();
31    let func_name = proc_macro2::TokenStream::from(TokenStream::from(func_name));
32    let user_process_func = proc_macro2::TokenStream::from(input);
33    let extern_c_process = quote! {
34        use tugraph_plugin_util::lgraph_api_graph_db_t;
35        use tugraph_plugin_util::CxxString;
36        use tugraph_plugin_util::Graph as TuGraph;
37        #[allow(clippy::missing_safety_doc)]
38        #[no_mangle]
39        pub unsafe extern "C" fn Process(graph_db: *mut lgraph_api_graph_db_t, request: *const CxxString, response: *mut CxxString) -> bool {
40            let mut graph = TuGraph::from_ptr(graph_db);
41            let request = if request.is_null() {
42                ""
43            } else {
44                (*request).to_str().unwrap()
45            };
46            // nest user defined process function
47            #user_process_func
48
49            let result = #func_name(&mut graph, request);
50            ::std::mem::forget(graph);
51
52            match result {
53                Ok(val) => {
54                    if !response.is_null() {
55                        let mut reponse = ::std::pin::Pin::new_unchecked(&mut *response);
56                        reponse.as_mut().clear();
57                        reponse.as_mut().push_str(val.as_str())
58                    }
59                    true
60                }
61                Err(e) => {
62                    eprintln!("run rust plugin failed: {:?}", e);
63                    false
64                }
65            }
66        }
67    };
68    TokenStream::from(extern_c_process)
69}