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 convert_case::{Case, Casing};
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote, ToTokens};
use syn::{punctuated::Punctuated, Ident, Token, Type};

use crate::{command_enum_parsing::Field, DataCommandEnum};

use super::get_input_type_of_bare_fn_field;

pub fn command_enum(input: &DataCommandEnum) -> TokenStream2 {
    let (fields, namespace_enums): (TokenStream2, TokenStream2) =
        turn_fields_to_enum(&input.fields);

    quote! {
        #[derive(Debug)]
        pub enum Command {
            #fields
        }
        #namespace_enums
    }
}

fn turn_fields_to_enum(fields: &Punctuated<Field, Token![,]>) -> (TokenStream2, TokenStream2) {
    let output: Vec<_> = fields
        .iter()
        .map(|field| turn_struct_field_to_enum(field))
        .collect();

    let mut fields_output: TokenStream2 = Default::default();
    let mut namespace_enums_output: TokenStream2 = Default::default();

    for (fields, namespace_enum) in output {
        fields_output.extend(fields.to_token_stream());
        namespace_enums_output.extend(namespace_enum.to_token_stream());
    }

    (fields_output, namespace_enums_output)
}

fn turn_struct_field_to_enum(field: &Field) -> (TokenStream2, TokenStream2) {
    match field {
        Field::Function(fun_field) => {
            let field_name = format_ident!(
                "{}",
                fun_field
                    .name
                    .to_string()
                    .from_case(Case::Snake)
                    .to_case(Case::Pascal)
            );

            let input_type: Option<Type> = get_input_type_of_bare_fn_field(fun_field);

            match input_type {
                Some(input_type) => (
                    quote! {
                        #field_name(#input_type),
                    },
                    quote! {},
                ),
                None => (
                    quote! {
                        #field_name,
                    },
                    quote! {},
                ),
            }
        }
        Field::Namespace(namespace) => {
            let (namespace_output_fields, namespace_output_namespace_enums) =
                turn_fields_to_enum(&namespace.fields);
            let namespace_name: Ident = format_ident!(
                "{}",
                namespace
                    .path
                    .iter()
                    .map(|name| name.to_string())
                    .collect::<String>()
            );

            let new_namespace_name: Ident = format_ident!(
                "{}",
                namespace_name
                    .to_string()
                    .from_case(Case::Snake)
                    .to_case(Case::Pascal)
            );

            (
                quote! {
                    #new_namespace_name(#new_namespace_name),
                },
                quote! {
                    #[derive(Debug)]
                    pub enum #new_namespace_name {
                        #namespace_output_fields
                    }
                    #namespace_output_namespace_enums
                },
            )
        }
    }
}