mirror of
https://git.proxmox.com/git/proxmox
synced 2025-08-06 13:14:42 +00:00
api-macro: support 'async fn' with new async api method
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
7dadea06dd
commit
808035f524
@ -47,6 +47,7 @@ pub fn handle_method(mut attribs: JSONObject, mut func: syn::ItemFn) -> Result<T
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut wrapper_ts = TokenStream::new();
|
let mut wrapper_ts = TokenStream::new();
|
||||||
|
let is_async = func.sig.asyncness.is_some();
|
||||||
let api_func_name = handle_function_signature(
|
let api_func_name = handle_function_signature(
|
||||||
&mut input_schema,
|
&mut input_schema,
|
||||||
&mut returns_schema,
|
&mut returns_schema,
|
||||||
@ -77,10 +78,16 @@ pub fn handle_method(mut attribs: JSONObject, mut func: syn::ItemFn) -> Result<T
|
|||||||
func.sig.ident.span(),
|
func.sig.ident.span(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let api_handler = if is_async {
|
||||||
|
quote! { ::proxmox::api::ApiHandler::Async(&#api_func_name) }
|
||||||
|
} else {
|
||||||
|
quote! { ::proxmox::api::ApiHandler::Sync(&#api_func_name) }
|
||||||
|
};
|
||||||
|
|
||||||
Ok(quote_spanned! { func.sig.span() =>
|
Ok(quote_spanned! { func.sig.span() =>
|
||||||
#vis const #api_method_name: ::proxmox::api::ApiMethod =
|
#vis const #api_method_name: ::proxmox::api::ApiMethod =
|
||||||
::proxmox::api::ApiMethod::new(
|
::proxmox::api::ApiMethod::new(
|
||||||
&::proxmox::api::ApiHandler::Sync(&#api_func_name),
|
&#api_handler,
|
||||||
&#input_schema,
|
&#input_schema,
|
||||||
)
|
)
|
||||||
#returns_schema
|
#returns_schema
|
||||||
@ -159,10 +166,7 @@ fn handle_function_signature(
|
|||||||
wrapper_ts: &mut TokenStream,
|
wrapper_ts: &mut TokenStream,
|
||||||
) -> Result<Ident, Error> {
|
) -> Result<Ident, Error> {
|
||||||
let sig = &func.sig;
|
let sig = &func.sig;
|
||||||
|
let is_async = sig.asyncness.is_some();
|
||||||
if sig.asyncness.is_some() {
|
|
||||||
bail!(sig => "async fn is currently not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut api_method_param = None;
|
let mut api_method_param = None;
|
||||||
let mut rpc_env_param = None;
|
let mut rpc_env_param = None;
|
||||||
@ -296,7 +300,14 @@ fn handle_function_signature(
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
create_wrapper_function(input_schema, returns_schema, param_list, func, wrapper_ts)
|
create_wrapper_function(
|
||||||
|
input_schema,
|
||||||
|
returns_schema,
|
||||||
|
param_list,
|
||||||
|
func,
|
||||||
|
wrapper_ts,
|
||||||
|
is_async,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_api_method_type(ty: &syn::Type) -> bool {
|
fn is_api_method_type(ty: &syn::Type) -> bool {
|
||||||
@ -351,6 +362,7 @@ fn create_wrapper_function(
|
|||||||
param_list: Vec<(FieldName, ParameterType)>,
|
param_list: Vec<(FieldName, ParameterType)>,
|
||||||
func: &syn::ItemFn,
|
func: &syn::ItemFn,
|
||||||
wrapper_ts: &mut TokenStream,
|
wrapper_ts: &mut TokenStream,
|
||||||
|
is_async: bool,
|
||||||
) -> Result<Ident, Error> {
|
) -> Result<Ident, Error> {
|
||||||
let api_func_name = Ident::new(
|
let api_func_name = Ident::new(
|
||||||
&format!("api_function_{}", &func.sig.ident),
|
&format!("api_function_{}", &func.sig.ident),
|
||||||
@ -401,25 +413,53 @@ fn create_wrapper_function(
|
|||||||
// build the wrapping function:
|
// build the wrapping function:
|
||||||
let func_name = &func.sig.ident;
|
let func_name = &func.sig.ident;
|
||||||
|
|
||||||
|
let await_keyword = if is_async { Some(quote!(.await)) } else { None };
|
||||||
|
|
||||||
let question_mark = match func.sig.output {
|
let question_mark = match func.sig.output {
|
||||||
syn::ReturnType::Default => None,
|
syn::ReturnType::Default => None,
|
||||||
_ => Some(quote!(?)),
|
_ => Some(quote!(?)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let body = quote! {
|
||||||
|
if let ::serde_json::Value::Object(ref mut input_map) = &mut input_params {
|
||||||
|
#body
|
||||||
|
Ok(::serde_json::to_value(#func_name(#args) #await_keyword #question_mark)?)
|
||||||
|
} else {
|
||||||
|
::failure::bail!("api function wrapper called with a non-object json value");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_async {
|
||||||
|
wrapper_ts.extend(quote! {
|
||||||
|
fn #api_func_name<'a>(
|
||||||
|
mut input_params: ::serde_json::Value,
|
||||||
|
api_method_param: &'static ::proxmox::api::ApiMethod,
|
||||||
|
rpc_env_param: &'a mut dyn ::proxmox::api::RpcEnvironment,
|
||||||
|
) -> ::proxmox::api::ApiFuture<'a> {
|
||||||
|
//async fn func<'a>(
|
||||||
|
// mut input_params: ::serde_json::Value,
|
||||||
|
// api_method_param: &'static ::proxmox::api::ApiMethod,
|
||||||
|
// rpc_env_param: &'a mut dyn ::proxmox::api::RpcEnvironment,
|
||||||
|
//) -> ::std::result::Result<::serde_json::Value, ::failure::Error> {
|
||||||
|
// #body
|
||||||
|
//}
|
||||||
|
//::std::boxed::Box::pin(async move {
|
||||||
|
// func(input_params, api_method_param, rpc_env_param).await
|
||||||
|
//})
|
||||||
|
::std::boxed::Box::pin(async move { #body })
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
wrapper_ts.extend(quote! {
|
wrapper_ts.extend(quote! {
|
||||||
fn #api_func_name(
|
fn #api_func_name(
|
||||||
mut input_params: ::serde_json::Value,
|
mut input_params: ::serde_json::Value,
|
||||||
api_method_param: &::proxmox::api::ApiMethod,
|
api_method_param: &::proxmox::api::ApiMethod,
|
||||||
rpc_env_param: &mut dyn ::proxmox::api::RpcEnvironment,
|
rpc_env_param: &mut dyn ::proxmox::api::RpcEnvironment,
|
||||||
) -> Result<::serde_json::Value, ::failure::Error> {
|
) -> ::std::result::Result<::serde_json::Value, ::failure::Error> {
|
||||||
if let ::serde_json::Value::Object(ref mut input_map) = &mut input_params {
|
|
||||||
#body
|
#body
|
||||||
Ok(::serde_json::to_value(#func_name(#args) #question_mark)?)
|
|
||||||
} else {
|
|
||||||
::failure::bail!("api function wrapper called with a non-object json value");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Ok(api_func_name)
|
Ok(api_func_name)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use proxmox_api_macro::api;
|
use proxmox_api_macro::api;
|
||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
#[api(
|
#[api(
|
||||||
input: {
|
input: {
|
||||||
@ -16,3 +17,17 @@ pub fn hello(message: String) -> Result<(), Error> {
|
|||||||
println!("Hello there. {}", message);
|
println!("Hello there. {}", message);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
input: {
|
||||||
|
properties: {
|
||||||
|
num: {
|
||||||
|
description: "The version to upgrade to",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// Return the number...
|
||||||
|
pub async fn number(num: u32) -> Result<u32, Error> {
|
||||||
|
Ok(num)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user