essentia-codegen 0.1.5

Code generation utilities for Essentia Rust bindings
Documentation
use convert_case::{Case, Casing};

use essentia_core::Introspection;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use syn::Ident;

use crate::algorithm_generation::common::{
    data_type_to_phantom, sanitize_identifier_string, string_to_doc_comment,
};

fn generate_compute_docs<'a>(introspection: &Introspection) -> TokenStream {
    let mut doc_string_lines = vec!["Computes the algorithm with the given inputs.".to_string()];
    let mut inputs = introspection.inputs().peekable();

    if inputs.peek().is_some() {
        doc_string_lines.push("".to_string());
        doc_string_lines.push("# Inputs".to_string());

        for input in inputs {
            let input_name = sanitize_identifier_string(&input.name().to_case(Case::Snake));
            let description = input.description();
            doc_string_lines.push(format!("* `{}`: {}", input_name, description));
        }
    }

    string_to_doc_comment(&doc_string_lines.join("\n"))
}

pub fn generate_compute_function(
    algorithm_result_struct_name: Ident,
    introspection: &Introspection,
) -> TokenStream {
    let mut p = Vec::new();
    let mut set_statements = Vec::new();

    for input in introspection.inputs() {
        let input_name = input.name().to_case(Case::Snake);
        let ident = format_ident!("{}", sanitize_identifier_string(&input_name));
        let variant = data_type_to_phantom(&input.input_output_type());

        p.push(quote! { #ident: impl crate::data::TryIntoDataContainer<#variant> });
        set_statements.push(quote! {
            self.algorithm.set_input(#input_name, #ident)?;
        });
    }

    let doc_comment = generate_compute_docs(introspection);

    quote! {
        #doc_comment
        pub fn compute(&mut self, #(#p,)*) -> Result<#algorithm_result_struct_name<'a, '_>, crate::algorithm::ComputeError> {
            #(#set_statements)*

            Ok(#algorithm_result_struct_name {
                compute_result: self.algorithm.compute()?,
            })
        }
    }
}