use itertools::Itertools;
use proc_macro2::TokenStream;
use quote::quote;
use super::{doc_tokens, format_tokens};
use crate::Result;
use crate::codegen::{MethodHandler, ServiceHandler};
pub(crate) fn generate(service: &ServiceHandler<'_>) -> Result<String> {
let wrapper_ident = service.low_level_client_type(crate::codegen::ClientProtocol::Connect);
let inner_path = service.connect_inner_client_path()?;
let mod_path = service.models_path();
let result_path: syn::Path = service.config.client_result_path();
let method_tokens: Vec<TokenStream> = service.methods().map(connect_method).try_collect()?;
let tokens = quote! {
#![allow(unused_imports)]
use #result_path;
use #mod_path::*;
#[derive(Clone)]
pub struct #wrapper_ident<T = ::olai_http::connectrpc::CloudTransport>
where
T: ::connectrpc::client::ClientTransport,
{
pub(crate) inner: #inner_path<T>,
}
impl<T> #wrapper_ident<T>
where
T: ::connectrpc::client::ClientTransport,
<T::ResponseBody as ::http_body::Body>::Error: ::std::fmt::Display,
{
pub fn new(inner: #inner_path<T>) -> Self {
Self { inner }
}
pub fn from_transport(transport: T, config: ::connectrpc::client::ClientConfig) -> Self {
Self { inner: #inner_path::new(transport, config) }
}
#(#method_tokens)*
}
};
format_tokens(tokens)
}
fn connect_method(method: MethodHandler<'_>) -> Result<TokenStream> {
let doc_attrs = doc_tokens(method.plan.metadata.documentation.as_deref());
let method_name = method.plan.base_method_ident();
let input_type_ident = method.input_type().ok_or_else(|| {
crate::Error::Build(format!(
"Connect method `{}` has no input type (Empty input is unsupported)",
method.plan.handler_function_name
))
})?;
if let Some(output_type) = method.output_type() {
Ok(quote! {
#doc_attrs
pub async fn #method_name(&self, request: &#input_type_ident) -> Result<#output_type> {
let response = self
.inner
.#method_name(request.clone())
.await
.map_err(crate::error::from_connect_error)?;
Ok(response.into_owned())
}
})
} else {
Ok(quote! {
#doc_attrs
pub async fn #method_name(&self, request: &#input_type_ident) -> Result<()> {
self
.inner
.#method_name(request.clone())
.await
.map_err(crate::error::from_connect_error)?;
Ok(())
}
})
}
}