trixy 0.4.0

A rust crate used to generate multi-language apis for your application
Documentation
/*
* Copyright (C) 2023 - 2024:
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This file is part of the Trixy crate for Trinitrix.
*
* Trixy is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*/

use proc_macro2::TokenStream as TokenStream2;
use quote::quote;

use crate::parser::command_spec::{Attribute, Function, Identifier, NamedType, Type};

impl Function {
    pub fn to_auxiliary_c(&self, namespaces: &[&Identifier]) -> String {
        let doc_comments: String = Attribute::to_auxiliary_c_merged(&self.attributes);
        let ident = self.identifier.to_c_with_path(namespaces);
        let inputs: Vec<TokenStream2> = self
            .inputs
            .iter()
            .filter_map(|a| NamedType::to_auxiliary_c(a))
            .collect();

        let function_output = if let Some(out) = &self.output {
            if Type::is_void(self.output.as_ref()) {
                TokenStream2::default()
            } else {
                let type_name = &out.to_auxiliary_c(true, None);
                let comma = if !inputs.is_empty() {
                    quote! {
                        ,
                    }
                } else {
                    TokenStream2::default()
                };
                quote! {
                    #type_name trixy_output #comma
                }
            }
        } else {
            TokenStream2::default()
        };

        let output = quote! {
            extern int #ident(#function_output #(#inputs),*);
        };
        format!("{}{}\n", doc_comments, output)
    }

    pub fn to_auxiliary_c_namespace_init(&self, namespaces: &[&Identifier]) -> TokenStream2 {
        let ident = &self.identifier.to_rust();
        let full_ident = &self.identifier.to_c_with_path(namespaces);

        quote! {
            . #ident = #full_ident,
        }
    }

    pub fn to_auxiliary_c_typedef(&self) -> TokenStream2 {
        let ident = self.identifier.to_rust();

        let (output, output_comma) = if let Some(output) = &self.output {
            let output = output.to_auxiliary_c(true, None);
            (quote! { #output }, quote! {,})
        } else {
            (TokenStream2::default(), TokenStream2::default())
        };

        let initial_inputs: Vec<TokenStream2> = self
            .inputs
            .iter()
            .map(|named_type| (&named_type.r#type, &named_type.name))
            .filter_map(|(r#type, name)| r#type.to_auxiliary_c(false, Some(name)))
            .collect();

        let inputs: TokenStream2 = if self.inputs.is_empty() && output.is_empty() {
            quote! { void }
        } else if !self.inputs.is_empty() && !output.is_empty() {
            quote! {
                #output_comma #(#initial_inputs),*
            }
        } else {
            quote! {
                #(#initial_inputs),*
            }
        };

        quote! {
            int (* #ident ) (#output #inputs);
        }
    }
}