use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use super::{ClientHandlerImpls, ClientProtocol, MethodHandler, ServiceHandler, format_tokens};
use crate::Result;
pub(super) fn generate(service: &ServiceHandler<'_>, impls: &ClientHandlerImpls) -> Result<String> {
let handlers_crate: syn::Path =
syn::parse_str(&impls.crate_path).map_err(|source| crate::Error::InvalidRustPath {
path: impls.crate_path.clone(),
message: "client handler_impls crate".to_string(),
source,
})?;
let module = format_ident!("{}", service.plan.base_path);
let trait_ident = format_ident!("{}", service.plan.handler_name);
let client_ident = service.low_level_client_type(ClientProtocol::Rest);
let mod_path = service.models_path();
let methods = service
.rest_methods()
.map(|m| forward_method(&m, &client_ident, &handlers_crate));
let tokens = quote! {
#![allow(unused_imports)]
use #mod_path::*;
use super::client::#client_ident;
#[::async_trait::async_trait]
impl<Cx: Send + 'static> #handlers_crate::#module::#trait_ident<Cx> for #client_ident {
#(#methods)*
}
};
format_tokens(tokens)
}
fn forward_method(
method: &MethodHandler<'_>,
client_ident: &syn::Ident,
handlers_crate: &syn::Path,
) -> TokenStream {
let method_name = method.plan.base_method_ident();
let input_type = method.input_type();
let output_type = if method.plan.has_response {
let output = method.output_type();
quote! { #output }
} else {
quote! { () }
};
quote! {
async fn #method_name(
&self,
request: #input_type,
_context: Cx,
) -> #handlers_crate::Result<#output_type> {
#client_ident::#method_name(self, &request)
.await
.map_err(::core::convert::Into::into)
}
}
}