tugraph_plugin_util-proc_macros 0.1.1

A helper crate for writing plugins for TuGraph
Documentation
// Copyright 2023 antkiller
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use proc_macro::{TokenStream, TokenTree::Ident};
use quote::quote;

/// A helper attribute macro brings easy life to write tugraph rust procedure
#[proc_macro_attribute]
pub fn tugraph_plugin(_attr: TokenStream, input: TokenStream) -> TokenStream {
    // skip the first identifier(keyword) `fn`
    // the second identifier is name of function.
    let func_name = input
        .clone()
        .into_iter()
        .find_map(|tt| match tt {
            Ident(ref name) if name.to_string() != "fn" && name.to_string() != "pub" => Some(tt),
            _ => None,
        })
        .unwrap();
    let func_name = proc_macro2::TokenStream::from(TokenStream::from(func_name));
    let user_process_func = proc_macro2::TokenStream::from(input);
    let extern_c_process = quote! {
        use tugraph_plugin_util::lgraph_api_graph_db_t;
        use tugraph_plugin_util::CxxString;
        use tugraph_plugin_util::Graph as TuGraph;
        #[allow(clippy::missing_safety_doc)]
        #[no_mangle]
        pub unsafe extern "C" fn Process(graph_db: *mut lgraph_api_graph_db_t, request: *const CxxString, response: *mut CxxString) -> bool {
            let mut graph = TuGraph::from_ptr(graph_db);
            let request = if request.is_null() {
                ""
            } else {
                (*request).to_str().unwrap()
            };
            // nest user defined process function
            #user_process_func

            let result = #func_name(&mut graph, request);
            ::std::mem::forget(graph);

            match result {
                Ok(val) => {
                    if !response.is_null() {
                        let mut reponse = ::std::pin::Pin::new_unchecked(&mut *response);
                        reponse.as_mut().clear();
                        reponse.as_mut().push_str(val.as_str())
                    }
                    true
                }
                Err(e) => {
                    eprintln!("run rust plugin failed: {:?}", e);
                    false
                }
            }
        }
    };
    TokenStream::from(extern_c_process)
}