use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use crate::parser::command_spec::{Function, Identifier, NamedType, Type};
impl Function {
pub fn to_rust_identifier<F>(
&self,
input_fmt_fn: fn(&NamedType) -> TokenStream2,
output_fmt_fn: F,
) -> TokenStream2
where
F: Fn(&Type) -> TokenStream2,
{
let ident = self.identifier.to_rust();
let inputs: Vec<TokenStream2> = self
.inputs
.iter()
.map(input_fmt_fn)
.filter(|a| !a.is_empty())
.collect();
let output = &self.output;
if inputs.is_empty() && output.is_none() {
quote! {
#ident
}
} else if output.is_some() && !Type::is_void(output.as_ref()) {
let output = output_fmt_fn(&output.as_ref().expect("We checked"));
quote! {
#ident {
trixy_output: #output ,
#(#inputs),*
}
}
} else if (output.is_none() || Type::is_void(output.as_ref())) && !inputs.is_empty() {
quote! {
#ident { #(#inputs),* }
}
} else {
unreachable!("All other conditions should be met")
}
}
pub fn to_rust(&self, _namespaces: &[&Identifier]) -> TokenStream2 {
let doc_comments: TokenStream2 = self
.attributes
.iter()
.map(|attr| attr.to_rust(&self.identifier))
.collect();
let function_ident = self.to_rust_identifier(
|a| NamedType::to_rust(a).unwrap_or(TokenStream2::default()),
move |r#type| {
let ident = r#type.to_c();
quote! {
trixy::oneshot::Sender<#ident>
}
},
);
quote! {
#doc_comments
#[allow(non_camel_case_types)]
#function_ident
}
}
}